Sorguyu Kısma


19

Her zaman hayatın keyiflerini bir web vekili olarak deneyimlemenin denemelerini ve sıkıntılarını düşündüğünüzü biliyorum. Dürüst olmak gerekirse, kim yapmadı? Bugün bu hedefi (en azından bir kısmını) gerçekleştirmekle görevlendirildiniz. Web sitesi X, günlük olarak çok fazla trafik alıyor ve hassas bilgileri sorgu parametreleri aracılığıyla iletmekte ısrar eden çok sayıda kullanıcı (kullanıcılar aptalca) nedeniyle bir PaaS (açıkça bu, Hizmet olarak Proxy'yi ifade ediyor) arıyor. Göreviniz, isteği orijinal hedefine yönlendirmeden önce tüm hassas sorgu parametrelerini istekten kaldırmaktır.

Giriş

  • RFC3986 Bölüm 3'te URI dilbilgisini izleyen iyi biçimlendirilmiş mutlak bir HTTP URL'si .
    • Hiçbir parça olmadığını varsayabilirsiniz.
    • Köşeli parantez içindeki herhangi bir şeyin isteğe bağlı olduğunu belirten kısa biçim örneği: http[s]://[user:pass@]host.name.com[:port]/[?param1=value1&param2=value2...]
  • Kaldırılacak sorgu parametrelerinin listesi.

Çıktı

Giriş listesinde tanımlanan parametreler olmadan değiştirilmiş HTTP URL'si.

Örnekler

http://example.com/ [foo]
> http://example.com/

http://example.com/?foo=bar []
> http://example.com/?foo=bar

http://example.com/ []
> http://example.com/

http://example.com/?foo=1&bar=2&baz=3 [foo,baz]
> http://example.com/?bar=2

http://example.com/?foo=1&bar=2&baz=3 [foo,bar,baz]
> http://example.com/

http://example.com/?foo&bar=2&baz= [foo,baz]
> http://example.com/?bar=2

http://example.com/?abc=1&def=2&baz=foo [foo,bar]
> http://example.com/?abc=1&def=2&baz=foo

http://example.com/?foobar=baz [foo]
> http://example.com/?foobar=baz

http://foo:foo@foo.com:8080/?foo=1&bar=foo [foo]
> http://foo:foo@foo.com:8080/?bar=foo

puanlama

Bu , bu yüzden en kısa cevap (bayt cinsinden) kazanır.


1
URL ve sorgu parametrelerinin her birini ayrı satırlarda alabilir miyim?
seshoumara

1
Can &parametreler arasındaki dışında herhangi bir yerde görünür?
Riley

ayrıca örneğin şifre bir içerebilir ?? Ayrıca sipariş olduğu gibi tutulmalı mı?
KarlKastor

&Bir sorgu parametresinin parçasıysa, doğru şekilde urlencocode edilmelidir%26
Poke

1
Görünüşe göre, http://foo:&foo=x@foo.com:8080/?foo=1&bar=fooRFC tarafından izin verilir. Bu, mevcut çözümlerin bir demetini kırmalıdır. : D (Kural userinfo, &=
rezerve edilmemiş

Yanıtlar:


6

GNU sed 98 96 88 80 77 74 69 59 54 (-r için 48 + 1) 49

:;s,(.+)(=[^&]*[& ]|&)(.*)\1,\3 ,
t;s,[?&]? .*,,

Kaldırılacak parametrelerin listesi boşluklarla ayrılır.

$ echo 'http://example.com/?foo=1&bar=2&baz=3 foo bar baz' | sed -rf sed.txt
http://example.com/

$ echo 'http://example.com/?foo&bar=2&baz= foo baz' | sed -rf sed.txt
http://example.com/?bar=2

$ echo 'http://example.com/' | sed -rf sed.txt
http://example.com/

Mevcut kod düzenlemenizde, OP'nin sorusundan gelen birden fazla test , elde edilen URL'de bir iz &veya ?karakter verir .
seshoumara

@seshoumara Bunu nasıl özlediğimi bilmiyorum ... Neyse ki bu sadece 1 baytlık bir fark.
Riley

96, 77 ve 59 bayt kod sürümleri düzenleme geçmişinizde bulunamadı. Düzenleme 7 başlığı, düzenleme 6'ya kıyasla 10 bayt daha az gösterdi, ancak kod değiştirilmemişti. Yine de harika golf oynuyor!
seshoumara

1
@seshoumara Bazı düzenlemeleri birleştirdiğini düşünüyorum çünkü küçükler (sadece birkaç karakteri siliyorlar).
Riley

@seshoumara Sanırım onları birleştirdi çünkü birbirlerinden 5 dakika içinde birden fazla düzenleme yaptım.
Riley

5

JavaScript (ES6), 62 60 bayt

f=
(s,a,u=new URL(s))=>a.map(e=>u.searchParams.delete(e))&&''+u
;
s.value=document.URL;
<div oninput=o.textContent=f(s.value,a.value.split`\n`)><input id=s><br><textarea id=a></textarea><pre id=o>

Düzenleme: @Shaggy sayesinde 2 bayt kaydedildi.


.hrefSonunda bırakarak 5 bayt kaydedebilirsiniz .
Shaggy

@Shaggy Bu bir dize döndürmezdi ... Buna izin verilmediğini düşünüyordum.
Neil

Nasıl çıkardığınıza bağlıdır. Örneğin, sizde alertolduğu gibi veya (metin) düğümüne ekleme hrefözelliğini kullanırsanız, size nesnenin özelliğini verecektir . Konsola oturum açarsanız, size tam nesneyi verecektir. Bu Fiddle'a bakın .
Shaggy

1
@Shaggy Ah, bu yüzden dizeleyerek kesinlikle 2 bayt kaydedebilirim, teşekkürler.
Neil

3

PHP, 90 Bayt

<?=trim(preg_replace("#(?<=\?|&)(".join("|",$_GET[r]).")(=.*)?(&|$)#U","",$_GET[u]),"?&");

-11 Bayt ise? veya sonunda izin verilir

Önceki Sürüm 140 Bytes

<?=substr($u=$_GET[u],0,strpos($u,"?")+!!$j=join("&",preg_grep("#^(".join("|",$_GET[r]).")(=|$)#",explode("&",parse_url($u)[query]),1))).$j;

+2 bayt: Alternatifler parantez içinde olmalıdır veya ^/ (.*|$)ilk / son alternatifin bir parçası olacaktır.
Titus

-2 bayt: kaldır .*. veya (-5) (=.*|$)ile değiştirin \b.
Titus

Kişisel regexp'in gibi görünecek #^foo|bar(=.*|$)#olan ile aynıdır #(^foo)|(bar=.*|bar$))#. Ama öyle olmalı #(foo|bar)(=.*|$)#.
Titus

@Titus Haklısın benim hatam
Jörg Hülsermann

Güzel! İddiaları düşünmedim; bu yüzden geri düştüm array_map(ve ne kadar kısa olabileceğine şaşırdım).
Titus

2

PHP 120 110 bayt

preg_replace ve dizi fonksiyonları ile: (esinlenerek Jörg )

<?=preg_replace(array_map(function($s){return"#(\\?|&)$s(=.*)?(&|$)#U";},array_slice($argv,2)),"\1",$argv[1]);

dosyaya kaydet, ile ara php <scriptname> <uri> <parametername> <parametername> ...

parse_str ve http_build_query ile (120 bayt):

parse_str(end($u=explode('?',$argv[1])),$a);for($i=$argc;$i-->1;)unset($a[$argv[$i]]);echo"$u[0]?".http_build_query($a);

ile koş php -r <code> <uri> <parametername> <parametername> ...


parse_str? http_build_query? Kod golf bile, iş için doğru araçları kullanarak çalışan birini görmek için çok mutluyum. URL / SQL sorgusu / regexp / HTML olduğu için ortaya çıkan hatalar "sadece dizelerdir", kolayca önlenebildikleri kadar çoktur.
Daerdemandt

Belki daha fazla ilham almak için. I got You
Jörg Hülsermann

@Lynn Beni izlemekten daha iyi yapacak bir şeyin yok mu?
Titus

2

Java 7, 127 bayt

String a(String a,String[]b){for(String c:b)a=a.replaceAll("(?<=[?&])"+c+"(=[^&]*)?(&|$)","");return a.replaceAll("[?&]$","");}

açıklama

String sanitize(String url, String[] params) {
    for (String param : params) {
        // please don't modify function parameters in real code
        url=url.replaceAll("(?<=[?&])" // Look for a leading ? or & but don't consume it
            + param                    // Consume the key of the query param (assuming key=value syntax)
            + "(=[^&]*)?"              // Consume the value of the query param if it exists
            + "(&|$)","");             // Consume the trailing & unless we're at the end of the url and replace with nothing
    }
    url = url.replaceAll("[?&]$",""); // If we remove all of the params then we'll have a trailing ? which needs to be removed
                                      // If we remove the last param only then we could have a trailing & which also needs to be removed
                                      // We will only run into one of these scenarios
    return url;
}

Ideone


Bu benim için Java 8 kullanıyorum 4., 5., 6., ve 9. örneklerini kullanarak benim için başarısız, o olabilir. Her ne kadar C # eşdeğerini denedi ve aynı durumlarda başarısız oldu, bu yüzden idunno.
Yodle

1
Boşver, test etme yöntemimi berbat ettim.
Yodle

2

C # 377 336 330 328 bayt (173 alt)

string n(string u,string[]r){var s=u.Split('?');if(s.Length<2)return u;var a=s[1].Contains("&")?s[1].Split('&'):new string[]{s[1]};int B=a.Length,i=0,C=i,c=B;for(;i<B;i++)foreach(var R in r)if(R==a[i].Split('=')[0]){a[i]="";c--;}var t=s[0];t+=c>0?"?":"";for(i=0;i<a.Length;i++)if(a[i]!=""){t+=a[i];C++;if(C!=c)t+="&";}return t;}

Ungolfed tam programı:

using System;
class a
{
    static void Main()
    {
        string input = Console.ReadLine();
        string url = input.Split(' ')[0];
        string r = input.Split(' ')[1];
        r = r.Replace("[", "").Replace("]","");
        string[] remove = r.Split(',');
        a b = new a();
        Console.WriteLine(b.n(url, remove));
    }
    string n(string u,string[]r)
    {
        var s=u.Split('?');
        if(s.Length<2)return u;
        var a=s[1].Contains("&")?s[1].Split('&'):new string[]{s[1]};
        int B=a.Length,i=0,C=i,c=B;
        for(;i<B;i++)
            foreach(var R in r)
                if(R==a[i].Split('=')[0])
                {
                    a[i]="";
                    c--;
                }
        var t=s[0];
        t+=c>0?"?":"";
        for(i=0;i<a.Length;i++)
            if(a[i]!="")
            {
                t+=a[i];
                C++;
                if (C!=c)t+="&";
            }
        return t;
    }
}

Muhtemelen çok verimli değil, ama bence işe yarıyor.

Alternatif olarak, @ Poke'un Java yöntemini kullanan 173 baytlık bir çözüm vardır. Yine de Regex için bir içe aktarma gerektirir, bu nedenle muhtemelen daha kısa olamaz.

using System.Text.RegularExpressions;string m(string a,string[]b){foreach(var c in b)a=Regex.Replace(a,$"(?<=[?&]){c}(=[^&]*)?(&|$)","");return Regex.Replace(a,"[?&]$","");}

2

Yakut, 1461401271116113 bayt

Düzenleme 2: kullanarak 6 bayt kaydedildi $1, $2ve $*değiştirerek ve 7 x.split("=")[0]için x[/\w+/]
düzenleme 3: kullanılarak kaydedildi 6 bayt *yerine .join, gereksiz boşluklar 2 bayt kaydedildi
eşdeğer satır içinde (değiştirildi düzenli ifade yeniden formüle tarafından kaydedilen 3 bayt düzenlemek 4 $*[1][/([^?]*)\??(.*)/,1]ve koymak atandığı gibi a)
düzenleme 5: ($*[2].scan(r=/\w+/)&[x[r]])[0]yerine kullanarak 3 bayt kaydedildi$*[2].scan(r=/\w+/).include?(x[r])

Programı çalıştırırken girdi olduğu varsayılarak:

a,b=$*[1][/([^?]*)\??(.*)/,1],$2.split("&").reject{|x|($*[2].scan(r=/\w+/)&[x[r]])[0]}*"&"
puts(b[0] ?a+"?"+b: a)

açıklama

a,b=$*[1][/([^?]*)\??(.*)/,1],$2.split("&")

Bu, komut satırında verilen URL'yi ayrıştırır ve eşleşmeleri $1ve içine kaydeder $2. $*[1][/([^?]*)\??(.*)/,1]ayrıca içeride saklamak için ilk eşleşmeyi döndürürken, aikinci eşleşme $2 1 $ 'a bir noktaya izin verilir ve bbir dizi diziye ayrılır ...

.reject { |x|

... hepsini reddediyor ...

    ($*[2].scan(r=/\w+/)&[x[r]])[0]

... Biz (listeyi almak için) kelimeleri için tarama çünkü daha önce sözünü almak bu eserler ... '=' ikinci parametresi tarafından verilen isimlerin listeye dahil edildiğini daha önce bir dize var =ve görmek bu kelime ile listede &. Yana &getiriler (boş küme) "bulunamadı" boş bir dizi, kullandığımız hile almak için aşağıda açıklanan nildizide hiçbir unsurlar varsa. aksi takdirde, doğruluk olarak sayılan ve bu dizeyi reddeden bir dize döndürürüz.

}*"&"

... ve kalan dizelere '&' ile birlikte katılın

Bu noktada, bURL için GET sorgu dizesi bulunur. Bu nedenle, sadece yazdırmamız gerekiyor.

puts(b[0] ?a+"?"+b: a)

Bu yakutta bir numara kullanır. b[0]olacak nilb boş dizi veya dize ise. Yani onun eğer truthy , (değil nilya falsebiz koyar gerek böylece), sonra dizideki en az bir eleman, orada a+"?"+bdoğru URL için. Aksi takdirde, sadece koyarız a, çünkü gösterilecek parametre yoktur

Not: Bu yanıt varsayar ? olamaz herhangi bir yerde görünür sorgudan URL'yi ayırmak için hariç. (bağlı RFC'den okuduğum şeye göre)

Ayrıca, bu benim ilk golf cevabım: D


2
PPCG'ye Hoşgeldiniz!
akrolit

1

Pip , 46 bayt

URL'yi stdin'den ve komut satırı bağımsız değişkenlerinden kaldırılmak üzere sorgu parametrelerini alır.

YgqR`\?.+`{s:J_@`^[^=]+`NIyFI@>a^'&[s&'?sJ'&]}

Çevrimiçi deneyin!

Açıklama:

 g               Local variable containing list of cmdline args
Y                Yank into global variable y so it's available inside the function
  q              Grab a line of stdin
   R`\?.+`{...}  Do a regex replace of everything from ? on, using a callback function:

s:J_@`^[^=]+`NIyFI@>a^'&[s&'?sJ'&]
                  @>a^'&            All but 1st char of match, split on &
                FI                  Filter on this function:
   _@`^[^=]+`                         Regex match: run of non = from beginning of string
                                      @ returns a list (here, of one item), so...
  J                                   Join to get a scalar
             NIy                      True if match not in y; false if in y
s:                                  Assign the filtered list to s
                        [        ]  Return a list containing:
                         s&'?       ? if s is nonempty, [] otherwise
                             sJ'&   s joined on &
                                    When used as a replacement, a list is first stringified
                                    (which, in the absence of flags, means concatenated)

1

PowerShell v3 +, 115 90 bayt

param($n,$z)$a,$b=$n-split'\?';($z|%{$b=$b-replace"(^|&)$_(=[^&]*)?(&|$)"});$a+"?"*!!$b+$b

Girdiyi $nURL olarak ve $zkaldırılacak parametreler olarak bir dizgi dizisi olarak alır. -splitgiriş URL'si açık olduğunda ?, ilk yarıyı içine $ave ikincisini içine kaydeder $b.

Daha sonra $b, bir döngü geçirilerek $z, -replaceyasaklanan her sorgu kelimesinde bunları kaldırmak için bir normal ifade gerçekleştirilerek yeniden formüle edilir . Ardından, çıktılar $a(değiştirilmemiş), artı var /olup olmadığına bağlı olarak artı artı var olup olmadığına bağlı olarak artı $ x.$b?$x


1

Pyth - 27 bayt

Kenny, dönüştürmek ve sonra ters çevirmek için yerleşik hakkında konuştuğunda haklıydı, ancak sağa çıkmak çok zor olacak.

.sjK\?mj\&f!}hcT\=Qcd\&czKK

Test Takımı .


1

Retina , 44 48 bayt

Çapraz 44 hala 44. Düzeltme için Martin'e teşekkürler.

[?&](?>([^ =&]+))[^ &]*(?=.* \1( |$))| .*

/&
/?

Gibi girdi alır uri param1 param2. Çevrimiçi deneyin!

açıklama

İlk değiştirme, sorgu dizesinden uygun parametreleri siler. yakalama grubu 1'de parametre adını depolayan [?&](?>([^ =&+))[^ &]*bir ?veya &, tam bir parametre adı ve (isteğe bağlı olarak) =ve bir değerle eşleşir . Ardından (?=.* \1( |$)), bu parametre adının silinecek parametreler listesinde görünüp görünmediğini kontrol eden bir ileriye bakar. Bir parametre bu koşullarla eşleşirse, kaldırılır (boş bir yedek ile değiştirilir).

Değişiklikler üst üste gelmiyor (ileriye doğru) ve soldan sağa doğru ilerliyor. URL'nin sonuna ulaşıldığında, .*şube silinecek parametre listesiyle eşleşir ve onu da kaldırır.

İkinci değiştirme, yalnızca ?ilk parametre silindiğinde yeni sorgu dizesinin başlamasını sağlar .


Ben de bir önek sonunda listede görünüyorsa bu da parametreleri kaldırır düşünüyorum (örn . Retina.tryitonline.net/… deneyin ). Bunu düzeltmenin bir yolu grup 1'i sarmaktır (?>...).
Martin Ender

@MartinEnder geri izleme olmayan alt ifadeler hakkında. Teşekkürler!
DLosc

0

Java 7, 203 bayt

String f(String u,List p)throws Exception{String[]g=u.split("\\?",2);String s="";if(g.length>1)for(String q:g[1].split("&")){if(p.indexOf(q.split("=")[0])<0){s+=s.isEmpty()?"?":"&";s+=q;}}return g[0]+s;}

Ungolfed:

  String f(String u, List p) throws Exception {
    String[] g = u.split("\\?", 2);
    String s = "";
    if (g.length > 1) for (String q : g[1].split("&")) {
      if (p.indexOf(q.split("=")[0]) < 0) {
        s += s.isEmpty() ? "?" : "&";
        s += q;
      }
    }
    return g[0] + s;
  }

Bu işlev tüm testleri geçer.


0

Python, 75 81 112 byte:

def Z(A,S):import re;F=A.rindex('/');print A[:F]+re.sub('|'.join(i+'(=\d?|&)&?'for i in S),'',A[F:]).strip('&?')

Adlandırılmış bir işlev. Girdi biçiminde alır

D(<String>,<Array>)

ve bir dize çıkarır.

Tüm Test Durumlarıyla Repl.it!


0

PHP, rakip değil

Heck, PHP bunun için yapıldı; neden gerçek URL'yi kullanmıyorsunuz?

<?foreach($_GET[x]as$w)unset($_GET[$w]);
echo http,s[$_SERVER[SERVER_PORT]-443],"://",
$u=$_SERVER[PHP_AUTH_USER],($p=$_SERVER[PHP_AUTH_PW])?":$p":"","@"[!$u&!$p],
"$_SERVER[HTTP_HOST]$_SERVER[SCRIPT_NAME]?",http_build_query($_GET);

Dosyaya kaydedin, istediğiniz sorgu dizesiyle artı arayın &x[]=x&x[]=<exclude1>&x[]=<exclude2>&....

Kullanıcı adı ve şifre başarısız olabilir (tarayıcınızın bunları kaldırıp kaldırmamasına bağlı olarak).
Will şifre ise başarısız 0.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.