Pobieranie części adresu URL (wyrażenie regularne)

134

Biorąc pod uwagę adres URL (pojedyncza linia):
http://test.example.com/dir/subdir/file.html

Jak wyodrębnić następujące części za pomocą wyrażeń regularnych:

  1. Subdomena (test)
  2. Domena (example.com)
  3. Ścieżka bez pliku (/ dir / subdir /)
  4. Plik (plik.html)
  5. Ścieżka z plikiem (/dir/subdir/file.html)
  6. Adres URL bez ścieżki ( http://test.example.com )
  7. (dodaj inne, które Twoim zdaniem byłyby przydatne)

Wyrażenie regularne powinno działać poprawnie, nawet jeśli wpiszę następujący adres URL:

http://example.example.com/example/example/example.html
pek
źródło
Nie jest to bezpośrednia odpowiedź, ale większość bibliotek internetowych ma funkcję, która wykonuje to zadanie. Funkcja jest często nazywana czymś podobnym do CrackUrl. Jeśli taka funkcja istnieje, użyj jej, prawie gwarantuje się, że będzie bardziej niezawodna i wydajniejsza niż jakikolwiek ręcznie wykonany kod.
Konrad Rudolph
7
Wyjaśnij nam, dlaczego należy to zrobić za pomocą wyrażenia regularnego. Jeśli to praca domowa, powiedz to, ponieważ to jest twoje ograniczenie. W przeciwnym razie istnieją lepsze rozwiązania specyficzne dla języka niż użycie wyrażenia regularnego.
Andy Lester
1
Linki do pierwszej i ostatniej próbki są uszkodzone.
Tin Man
Tutaj możesz dowiedzieć się, jak wyodrębnić schemat, domenę, TLD, port i ścieżkę zapytania: stackoverflow.com/questions/9760588/ ...
Paolo Rovelli

Odpowiedzi:

153

Pojedyncze wyrażenie regularne służące do analizowania i dzielenia pełnego adresu URL, w tym parametrów zapytania i kotwic, np

https://www.google.com/dir/1/2/search.html?arg=0-a&arg1=1-b&arg3-c#hash

^((http[s]?|ftp):\/)?\/?([^:\/\s]+)((\/\w+)*\/)([\w\-\.]+[^#?\s]+)(.*)?(#[\w\-]+)?$

Stanowiska RexEx:

url: RegExp ['$ &'],

protokół: RegExp. $ 2,

host: RegExp. $ 3,

ścieżka: RegExp. $ 4,

plik: RegExp. $ 6,

zapytanie: RegExp. $ 7,

hash: RegExp. 8 $

można następnie dość łatwo przeanalizować hosta (rozdzielany znakami „.”).

Co ja zrobi to stosowanie mniej więcej tak:

/*
    ^(.*:)//([A-Za-z0-9\-\.]+)(:[0-9]+)?(.*)$
*/
proto $1
host $2
port $3
the-rest $4

dalsza analiza „reszta” ma być jak najbardziej konkretna. Robienie tego w jednym wyrażeniu regularnym jest trochę szalone.

hometoast
źródło
4
Link codenippets.joyent.com/posts/show/523 nie działa od 20 października '10
W3Max
19
Problem polega na tym (.*)?, że ?część (0 lub 1) jest myląca, ponieważ gwiazda Kleene już akceptuje 0 lub więcej . Naprawiłem to, zmieniając (.*)?na (.+)?. Możesz też po prostu usunąć?
rossipedia
3
Cześć Dve, poprawiłem go trochę bardziej, aby wyodrębnić example.com z adresów URL takich jak http://www.example.com:8080/....Tutaj:^((http[s]?|ftp):\/\/)?\/?([^\/\.]+\.)*?([^\/\.]+\.[^:\/\s\.]{2,3}(\.[^:\/\s\.]{2,3})?(:\d+)?)($|\/)([^#?\s]+)?(.*?)?(#[\w\-]+)?$
mnacos
4
i dowód, że żadne ^((http[s]?|ftp):\/\/)?\/?([^\/\.]+\.)*?([^\/\.]+\.[^:\/\s\.]{2,3}(\.[^:\/\s\.]{2,3})?)(:\d+)?($|\/)([^#?\s]+)?(.*?)?(#[\w\-]+)?$
wyrażenie regularne
2
Zmodyfikowałem to wyrażenie regularne, aby zidentyfikować wszystkie części adresu URL (poprawiona wersja) - kod w Pythonie ^((?P<scheme>[^:/?#]+):(?=//))?(//)?(((?P<login>[^:]+)(?::(?P<password>[^@]+)?)?@)?(?P<host>[^@/?#:]*)(?::(?P<port>\d+)?)?)?(?P<path>[^?#]*)(\?(?P<query>[^#]*))?(#(?P<fragment>.*))? code Ten kod pokazujesz w akcji na pythex.org
arannasousa
82

Zdaję sobie sprawę, że spóźniłem się na imprezę, ale istnieje prosty sposób, aby przeglądarka przeanalizowała adres URL bez wyrażenia regularnego:

var a = document.createElement('a');
a.href = 'http://www.example.com:123/foo/bar.html?fox=trot#foo';

['href','protocol','host','hostname','port','pathname','search','hash'].forEach(function(k) {
    console.log(k+':', a[k]);
});

/*//Output:
href: http://www.example.com:123/foo/bar.html?fox=trot#foo
protocol: http:
host: www.example.com:123
hostname: www.example.com
port: 123
pathname: /foo/bar.html
search: ?fox=trot
hash: #foo
*/
Obrabować
źródło
9
Biorąc pod uwagę, że pierwotne pytanie zostało oznaczone jako „język-agnostyk”, jaki to język?
MarkHu
zwróć uwagę, że to rozwiązanie wymaga istnienia przedrostka protokołu, na przykład http://w celu poprawnego wyświetlania właściwości protokołu, hosta i nazwy hosta. W przeciwnym razie początek adresu URL do pierwszego ukośnika przechodzi do właściwości protokołu.
Oleksii Aza
Wierzę w to, choć proste, ale znacznie wolniejsze niż parsowanie RegEx.
demisx
Czy jest obsługiwany przez wszystkie przeglądarki?
sean
1
Jeśli idziemy w ten sposób, możesz też to zrobićvar url = new URL(someUrl)
gman
73

Spóźniłem się na imprezę o kilka lat, ale jestem zaskoczony, że nikt nie wspomniał, że specyfikacja Uniform Resource Identifier zawiera sekcję dotyczącą analizowania identyfikatorów URI za pomocą wyrażenia regularnego . Wyrażenie regularne, napisane przez Berners-Lee i wsp., To:

^(([^:/?#]+):)?(//([^/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))?
 12            3  4          5       6  7        8 9

Liczby w drugim wierszu powyżej służą jedynie do ułatwienia czytelności; wskazują punkty odniesienia dla każdego wyrażenia podrzędnego (tj. każdego sparowanego nawiasu). Odnosimy się do wartości dopasowanej do wyrażenia podrzędnego jako $. Na przykład dopasowanie powyższego wyrażenia do

http://www.ics.uci.edu/pub/ietf/uri/#Related

skutkuje następującymi dopasowaniami podwyrażenia:

$1 = http:
$2 = http
$3 = //www.ics.uci.edu
$4 = www.ics.uci.edu
$5 = /pub/ietf/uri/
$6 = <undefined>
$7 = <undefined>
$8 = #Related
$9 = Related

Co jest warte, odkryłem, że muszę uniknąć ukośników w JavaScript:

^(([^:\/?#]+):)?(\/\/([^\/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))?

gwg
źródło
4
świetna odpowiedź! Wybór czegoś z RFC z pewnością nigdy nie jest złym rozwiązaniem
Frankster
1
to nie analizuje parametrów zapytania
Rémy DAVID
2
To jest najlepsza sprawa. W szczególności dotyczy to dwóch problemów, które widziałem w przypadku innych 1:: Dotyczy to poprawnie innych protokołów, takich jak ftp://i mailto://. 2: Działa poprawnie z usernamei password. Te opcjonalne pola są oddzielone dwukropkiem, podobnie jak nazwa hosta i port, i spowoduje to błąd większości innych wyrażeń regularnych, które widziałem. @ RémyDAVID Również locationobiekt przeglądarki nie przetwarza zapytania w normalny sposób . Jeśli chcesz przeanalizować ciąg zapytania, zajrzyj do mojej małej biblioteki: uqs .
Stijn de Witt
2
Ta odpowiedź zasługuje na więcej głosów pozytywnych, ponieważ obejmuje prawie wszystkie protokoły.
Tianzhen Lin
2
Zrywa się, gdy protokół jest domniemany HTTP z nazwą użytkownika / hasłem (ezoteryczna i technicznie niepoprawna składnia, przyznaję): np. user:[email protected]- RFC 3986 mówi:A path segment that contains a colon character (e.g., "this:that") cannot be used as the first segment of a relative-path reference, as it would be mistaken for a scheme name. Such a segment must be preceded by a dot-segment (e.g., "./this:that") to make a relative- path reference.
Matt Chambers
33

Zauważyłem, że najwyżej oddana odpowiedź (odpowiedź hometoast) nie działa idealnie dla mnie. Dwa problemy:

  1. Nie obsługuje numeru portu.
  2. Część z krzyżykiem jest zepsuta.

Poniżej znajduje się zmodyfikowana wersja:

^((http[s]?|ftp):\/)?\/?([^:\/\s]+)(:([^\/]*))?((\/\w+)*\/)([\w\-\.]+[^#?\s]+)(\?([^#]*))?(#(.*))?$

Położenie części jest następujące:

int SCHEMA = 2, DOMAIN = 3, PORT = 5, PATH = 6, FILE = 8, QUERYSTRING = 9, HASH = 12

Edycja opublikowana przez użytkownika:

function getFileName(path) {
    return path.match(/^((http[s]?|ftp):\/)?\/?([^:\/\s]+)(:([^\/]*))?((\/[\w\/-]+)*\/)([\w\-\.]+[^#?\s]+)(\?([^#]*))?(#(.*))?$/i)[8];
}
mingfai
źródło
1
Uważaj, to nie zadziała, jeśli adres URL nie ma ścieżki po domenie - np. http://www.example.comLub jeśli ścieżka składa się z pojedynczego znaku, np http://www.example.com/a.
Fernando Correia
11

Potrzebowałem zwykłego wyrażenia, aby dopasować wszystkie adresy URL i utworzyłem ten:

/(?:([^\:]*)\:\/\/)?(?:([^\:\@]*)(?:\:([^\@]*))?\@)?(?:([^\/\:]*)\.(?=[^\.\/\:]*\.[^\.\/\:]*))?([^\.\/\:]*)(?:\.([^\/\.\:]*))?(?:\:([0-9]*))?(\/[^\?#]*(?=.*?\/)\/)?([^\?#]*)?(?:\?([^#]*))?(?:#(.*))?/

Pasuje do wszystkich adresów URL, dowolnego protokołu, a nawet adresów URL, takich jak

ftp://user:[email protected]:8080/dir1/dir2/file.php?param1=value1#hashtag

Wynik (w JavaScript) wygląda następująco:

["ftp", "user", "pass", "www.cs", "server", "com", "8080", "/dir1/dir2/", "file.php", "param1=value1", "hashtag"]

Adres URL, taki jak

mailto://[email protected]

wygląda tak:

["mailto", "admin", undefined, "www.cs", "server", "com", undefined, undefined, undefined, undefined, undefined] 
baadf00d
źródło
3
Jeśli chcesz dopasować całą domenę / adres IP (nie oddzielony kropkami), użyj tego:/(?:([^\:]*)\:\/\/)?(?:([^\:\@]*)(?:\:([^\@]*))?\@)?(?:([^\/\:]*))?(?:\:([0-9]*))?\/(\/[^\?#]*(?=.*?\/)\/)?([^\?#]*)?(?:\?([^#]*))?(?:#(.*))?/
lepe
11

Próbowałem rozwiązać ten problem w javascript, co powinno być obsługiwane przez:

var url = new URL('http://a:b@example.com:890/path/wah@t/foo.js?foo=bar&bingobang=&[email protected]#foobar/bing/bo@ng?bang');

ponieważ (przynajmniej w Chrome) analizuje do:

{
  "hash": "#foobar/bing/bo@ng?bang",
  "search": "?foo=bar&bingobang=&[email protected]",
  "pathname": "/path/wah@t/foo.js",
  "port": "890",
  "hostname": "example.com",
  "host": "example.com:890",
  "password": "b",
  "username": "a",
  "protocol": "http:",
  "origin": "http://example.com:890",
  "href": "http://a:[email protected]:890/path/wah@t/foo.js?foo=bar&bingobang=&[email protected]#foobar/bing/bo@ng?bang"
}

Jednak to nie jest przeglądarka internetowa ( https://developer.mozilla.org/en-US/docs/Web/API/URL ), więc zebrałem to razem, aby wyciągnąć te same części, co powyżej:

^(?:(?:(([^:\/#\?]+:)?(?:(?:\/\/)(?:(?:(?:([^:@\/#\?]+)(?:\:([^:@\/#\?]*))?)@)?(([^:\/#\?\]\[]+|\[[^\/\]@#?]+\])(?:\:([0-9]+))?))?)?)?((?:\/?(?:[^\/\?#]+\/+)*)(?:[^\?#]*)))?(\?[^#]+)?)(#.*)?

Kredyt za to wyrażenie regularne trafia do https://gist.github.com/rpflorence, który opublikował ten jsperf http://jsperf.com/url-parsing (pierwotnie znaleziony tutaj: https://gist.github.com/jlong/2428561 # comment-310066 ), który wymyślił wyrażenie regularne, na którym było to pierwotnie oparte.

Części są w następującej kolejności:

var keys = [
    "href",                    // http://user:[email protected]:81/directory/file.ext?query=1#anchor
    "origin",                  // http://user:[email protected]:81
    "protocol",                // http:
    "username",                // user
    "password",                // pass
    "host",                    // host.com:81
    "hostname",                // host.com
    "port",                    // 81
    "pathname",                // /directory/file.ext
    "search",                  // ?query=1
    "hash"                     // #anchor
];

Istnieje również mała biblioteka, która ją opakowuje i dostarcza parametry zapytania:

https://github.com/sadams/lite-url (dostępne również na bower)

Jeśli masz poprawę, utwórz żądanie ściągnięcia z większą liczbą testów, a ja zaakceptuję i połączę z podziękowaniami.

Sam Adams
źródło
To jest świetne, ale naprawdę przydałoby się z wersją taką jak ta, która wyciąga subdomeny zamiast zduplikowanego hosta, nazwa hosta. Więc gdybym miał http://test1.dev.mydomain.com/na przykład to by się wycofało test1.dev..
Lankymart
To działa bardzo dobrze. Szukałem sposobu na wyodrębnienie nietypowych parametrów uwierzytelniania z adresów URL i działa to pięknie.
Aaron M
6

Zaproponuj znacznie bardziej czytelne rozwiązanie (w Pythonie, ale dotyczy dowolnego wyrażenia regularnego):

def url_path_to_dict(path):
    pattern = (r'^'
               r'((?P<schema>.+?)://)?'
               r'((?P<user>.+?)(:(?P<password>.*?))?@)?'
               r'(?P<host>.*?)'
               r'(:(?P<port>\d+?))?'
               r'(?P<path>/.*?)?'
               r'(?P<query>[?].*?)?'
               r'$'
               )
    regex = re.compile(pattern)
    m = regex.match(path)
    d = m.groupdict() if m is not None else None

    return d

def main():
    print url_path_to_dict('http://example.example.com/example/example/example.html')

Wydruki:

{
'host': 'example.example.com', 
'user': None, 
'path': '/example/example/example.html', 
'query': None, 
'password': None, 
'port': None, 
'schema': 'http'
}
okigan
źródło
5

subdomena i domena są trudne, ponieważ subdomena może mieć kilka części, podobnie jak domena najwyższego poziomu, http://sub1.sub2.domain.co.uk/

 the path without the file : http://[^/]+/((?:[^/]+/)*(?:[^/]+$)?)  
 the file : http://[^/]+/(?:[^/]+/)*((?:[^/.]+\.)+[^/.]+)$  
 the path with the file : http://[^/]+/(.*)  
 the URL without the path : (http://[^/]+/)  

(Markdown nie jest zbyt przyjazny dla wyrażeń regularnych)

tgmdbm
źródło
2
Bardzo przydatne - dodałem dodatkowy, (http(s?)://[^/]+/)aby również pobrać https
Mojowen
5

Ta ulepszona wersja powinna działać równie niezawodnie jak parser.

   // Applies to URI, not just URL or URN:
   //    http://en.wikipedia.org/wiki/Uniform_Resource_Identifier#Relationship_to_URL_and_URN
   //
   // http://labs.apache.org/webarch/uri/rfc/rfc3986.html#regexp
   //
   // (?:([^:/?#]+):)?(?://([^/?#]*))?([^?#]*)(?:\?([^#]*))?(?:#(.*))?
   //
   // http://en.wikipedia.org/wiki/URI_scheme#Generic_syntax
   //
   // $@ matches the entire uri
   // $1 matches scheme (ftp, http, mailto, mshelp, ymsgr, etc)
   // $2 matches authority (host, user:pwd@host, etc)
   // $3 matches path
   // $4 matches query (http GET REST api, etc)
   // $5 matches fragment (html anchor, etc)
   //
   // Match specific schemes, non-optional authority, disallow white-space so can delimit in text, and allow 'www.' w/o scheme
   // Note the schemes must match ^[^\s|:/?#]+(?:\|[^\s|:/?#]+)*$
   //
   // (?:()(www\.[^\s/?#]+\.[^\s/?#]+)|(schemes)://([^\s/?#]*))([^\s?#]*)(?:\?([^\s#]*))?(#(\S*))?
   //
   // Validate the authority with an orthogonal RegExp, so the RegExp above won’t fail to match any valid urls.
   function uriRegExp( flags, schemes/* = null*/, noSubMatches/* = false*/ )
   {
      if( !schemes )
         schemes = '[^\\s:\/?#]+'
      else if( !RegExp( /^[^\s|:\/?#]+(?:\|[^\s|:\/?#]+)*$/ ).test( schemes ) )
         throw TypeError( 'expected URI schemes' )
      return noSubMatches ? new RegExp( '(?:www\\.[^\\s/?#]+\\.[^\\s/?#]+|' + schemes + '://[^\\s/?#]*)[^\\s?#]*(?:\\?[^\\s#]*)?(?:#\\S*)?', flags ) :
         new RegExp( '(?:()(www\\.[^\\s/?#]+\\.[^\\s/?#]+)|(' + schemes + ')://([^\\s/?#]*))([^\\s?#]*)(?:\\?([^\\s#]*))?(?:#(\\S*))?', flags )
   }

   // http://en.wikipedia.org/wiki/URI_scheme#Official_IANA-registered_schemes
   function uriSchemesRegExp()
   {
      return 'about|callto|ftp|gtalk|http|https|irc|ircs|javascript|mailto|mshelp|sftp|ssh|steam|tel|view-source|ymsgr'
   }
Shelby Moore
źródło
5

Spróbuj wykonać następujące czynności:

^((ht|f)tp(s?)\:\/\/|~/|/)?([\w]+:\w+@)?([a-zA-Z]{1}([\w\-]+\.)+([\w]{2,5}))(:[\d]{1,5})?((/?\w+/)+|/?)(\w+\.[\w]{3,4})?((\?\w+=\w+)?(&\w+=\w+)*)?

Obsługuje HTTP / FTP, subdomeny, foldery, pliki itp.

Znalazłem to z szybkiego wyszukiwania w Google:

http://geekswithblogs.net/casualjim/archive/2005/12/01/61722.aspx

Mark Ingram
źródło
4
/^((?P<scheme>https?|ftp):\/)?\/?((?P<username>.*?)(:(?P<password>.*?)|)@)?(?P<hostname>[^:\/\s]+)(?P<port>:([^\/]*))?(?P<path>(\/\w+)*\/)(?P<filename>[-\w.]+[^#?\s]*)?(?P<query>\?([^#]*))?(?P<fragment>#(.*))?$/

Z mojej odpowiedzi na podobne pytanie . Działa lepiej niż niektóre z wymienionych, ponieważ miały pewne błędy (takie jak brak obsługi nazwy użytkownika / hasła, brak obsługi jednoznakowych nazw plików, zepsute identyfikatory fragmentów).

strager
źródło
2

Możesz uzyskać wszystkie adresy http / https, host, port, ścieżkę, a także zapytania za pomocą obiektu Uri w .NET. tylko trudnym zadaniem jest rozbicie hosta na subdomenę, nazwę domeny i TLD.

Nie ma takiego standardu i nie można po prostu użyć analizy ciągów lub wyrażenia regularnego, aby uzyskać poprawny wynik. Na początku używam funkcji RegEx, ale nie wszystkie adresy URL mogą być poprawnie przeanalizowane poddomeny. Praktyczny sposób polega na użyciu listy domen najwyższego poziomu. Po zdefiniowaniu TLD dla adresu URL lewa część to domena, a pozostała część to subdomena.

Jednak lista musi go utrzymać, ponieważ możliwe są nowe domeny TLD. W chwili obecnej wiem, że publicsuffix.org utrzymuje najnowszą listę i możesz użyć narzędzi do parsera nazw domen z kodu Google, aby przeanalizować publiczną listę sufiksów i łatwo uzyskać subdomenę, domenę i TLD za pomocą obiektu DomainName: domainName.SubDomain, domainName .Domain i domainName.TLD.

Ta odpowiedź również jest pomocna: pobierz subdomenę z adresu URL

CaLLMeLaNN

CallMeLaNN
źródło
2

Oto jeden, który jest kompletny i nie opiera się na żadnym protokole.

function getServerURL(url) {
        var m = url.match("(^(?:(?:.*?)?//)?[^/?#;]*)");
        console.log(m[1]) // Remove this
        return m[1];
    }

getServerURL("http://dev.test.se")
getServerURL("http://dev.test.se/")
getServerURL("//ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js")
getServerURL("//")
getServerURL("www.dev.test.se/sdas/dsads")
getServerURL("www.dev.test.se/")
getServerURL("www.dev.test.se?abc=32")
getServerURL("www.dev.test.se#abc")
getServerURL("//dev.test.se?sads")
getServerURL("http://www.dev.test.se#321")
getServerURL("http://localhost:8080/sads")
getServerURL("https://localhost:8080?sdsa")

Wydruki

http://dev.test.se

http://dev.test.se

//ajax.googleapis.com

//

www.dev.test.se

www.dev.test.se

www.dev.test.se

www.dev.test.se

//dev.test.se

http://www.dev.test.se

http://localhost:8080

https://localhost:8080
mmm
źródło
2

Żadne z powyższych nie działało dla mnie. Oto, czego ostatecznie użyłem:

/^(?:((?:https?|s?ftp):)\/\/)([^:\/\s]+)(?::(\d*))?(?:\/([^\s?#]+)?([?][^?#]*)?(#.*)?)?/
Skone
źródło
2

Podoba mi się wyrażenie regularne opublikowane w „Javascript: The Good Parts”. Nie jest za krótki i niezbyt skomplikowany. Ta strona na github zawiera również kod JavaScript, który z niej korzysta. Ale można go dostosować do dowolnego języka. https://gist.github.com/voodooGQ/4057330

Yetti99
źródło
1

Java oferuje klasę URL, która to zrobi. Zapytanie o obiekty URL.

Na marginesie, PHP oferuje parse_url () .

Chris Bartow
źródło
Wygląda na to, że to nie analizuje subdomeny?
Chris Dutrow
Asker poprosił o wyrażenie regularne. Klasa URL otworzy połączenie, gdy je utworzysz.
MikeNereson
„Klasa URL otworzy połączenie, gdy ją utworzysz” - to niepoprawne, tylko wtedy, gdy wywołujesz metody takie jak connect (). Ale to prawda, że ​​java.net.URL jest dość ciężki. W tym przypadku lepszym rozwiązaniem jest java.net.URI.
jcsahnwaldt Przywróć Monikę
1

Nie radziłbym używać wyrażenia regularnego. Wywołanie API, takie jak WinHttpCrackUrl (), jest mniej podatne na błędy.

http://msdn.microsoft.com/en-us/library/aa384092%28VS.85%29.aspx

Jason
źródło
5
A także bardzo specyficzne dla platformy.
Andir,
2
Myślę, że chodziło o to, aby użyć biblioteki, zamiast wymyślać koło na nowo. Ruby, Python, Perl mają narzędzia do rozrywania adresów URL, więc weź je zamiast implementować zły wzorzec.
Tin Man
1

Wypróbowałem kilka z nich, które nie zaspokajały moich potrzeb, szczególnie te z najwyższą liczbą głosów, które nie łapały adresu URL bez ścieżki ( http://example.com/ )

również brak nazw grup sprawił, że nie można go było używać w ansible (a może brakuje moich umiejętności jinja2).

więc to jest moja wersja nieco zmodyfikowana, a źródło jest tutaj wersją o największej liczbie głosów:

^((?P<protocol>http[s]?|ftp):\/)?\/?(?P<host>[^:\/\s]+)(?P<path>((\/\w+)*\/)([\w\-\.]+[^#?\s]+))*(.*)?(#[\w\-]+)?$
Gil Zellner
źródło
0

Korzystanie z http://www.fileformat.info/tool/regex.htm wyrażenia regularnego hometoast działa świetnie.

Ale o to chodzi, chcę używać różnych wzorców regex w różnych sytuacjach w moim programie.

Na przykład mam ten adres URL i mam wyliczenie, które zawiera listę wszystkich obsługiwanych adresów URL w moim programie. Każdy obiekt w wyliczeniu ma metodę getRegexPattern, która zwraca wzorzec wyrażenia regularnego, który zostanie następnie użyty do porównania z adresem URL. Jeśli określony wzorzec wyrażenia regularnego zwraca prawdę, wiem, że ten adres URL jest obsługiwany przez mój program. Tak więc każde wyliczenie ma swoje własne wyrażenie regularne w zależności od tego, gdzie powinno szukać w adresie URL.

Sugestia Hometoast jest świetna, ale w moim przypadku myślę, że nie pomogłaby (chyba że skopiuję wklej ten sam regex we wszystkich wyliczeniach).

Dlatego chciałem, aby odpowiedź zawierała wyrażenie regularne dla każdej sytuacji z osobna. Chociaż +1 dla hometoast. ;)

pek
źródło
0

Wiem, że twierdzisz, że jesteś agnostykiem językowym, ale czy możesz nam powiedzieć, czego używasz, abyśmy wiedzieli, jakie masz możliwości wyrażenia regularnego?

Jeśli masz możliwości dopasowań nieprzechwytywanych, możesz zmodyfikować wyrażenie hometoast, aby podwyrażenia, których nie chcesz przechwytywać, były skonfigurowane w następujący sposób:

(?:SOMESTUFF)

Nadal musiałbyś skopiować i wkleić (i nieznacznie zmodyfikować) Regex w wielu miejscach, ale ma to sens - nie tylko sprawdzasz, czy podwyrażenie istnieje, ale raczej czy istnieje jako część adresu URL . Używanie modyfikatora nieprzechwytującego dla podwyrażeń może dać ci to, czego potrzebujesz, i nic więcej, co, jeśli dobrze cię czytam, jest tym, czego chcesz.

Podobnie jak mała, mała uwaga, wyrażenie hometoast nie musi umieszczać nawiasów wokół „s” dla „https”, ponieważ ma tam tylko jeden znak. Kwantyfikatory określają ilościowo jeden znak (lub klasę znaków lub podwyrażenie) bezpośrednio poprzedzający je. Więc:

https?

pasuje dobrze do „http” lub „https”.

Brian Warshaw
źródło
0

regexp, aby uzyskać ścieżkę adresu URL bez pliku.

url = ' http: // domain / dir1 / dir2 / somefile ' url.scan (/ ^ (http: // [^ /] +) ((?: / [^ /] +) + (? = /)) ? /? (?: [^ /] +)? $ / i) .to_s

Przydatne może być dodanie względnej ścieżki do tego adresu URL.


źródło
0

Wyrażenie regularne do pełnego parsowania jest dość przerażające. Dodałem nazwane odwołania wsteczne dla czytelności i podzieliłem każdą część na osobne wiersze, ale nadal wygląda to tak:

^(?:(?P<protocol>\w+(?=:\/\/))(?::\/\/))?
(?:(?P<host>(?:(?:&(?:amp|apos|gt|lt|nbsp|quot|bull|hellip|[lr][ds]quo|[mn]dash|permil|\#[1-9][0-9]{1,3}|[A-Za-z][0-9A-Za-z]+);)|[^\/?#:]+)(?::(?P<port>[0-9]+))?)\/)?
(?:(?P<path>(?:(?:&(?:amp|apos|gt|lt|nbsp|quot|bull|hellip|[lr][ds]quo|[mn]dash|permil|\#[1-9][0-9]{1,3}|[A-Za-z][0-9A-Za-z]+);)|[^?#])+)\/)?
(?P<file>(?:(?:&(?:amp|apos|gt|lt|nbsp|quot|bull|hellip|[lr][ds]quo|[mn]dash|permil|\#[1-9][0-9]{1,3}|[A-Za-z][0-9A-Za-z]+);)|[^?#])+)
(?:\?(?P<querystring>(?:(?:&(?:amp|apos|gt|lt|nbsp|quot|bull|hellip|[lr][ds]quo|[mn]dash|permil|\#[1-9][0-9]{1,3}|[A-Za-z][0-9A-Za-z]+);)|[^#])+))?
(?:#(?P<fragment>.*))?$

Rzecz, która wymaga, aby była tak szczegółowa, polega na tym, że z wyjątkiem protokołu lub portu dowolna część może zawierać encje HTML, co sprawia, że ​​określenie fragmentu jest dość trudne. Tak więc w kilku ostatnich przypadkach - host, ścieżka, plik, kwerenda i fragment, zezwalamy na dowolną jednostkę html lub dowolny znak, który nie jest ?lub #. Wyrażenie regularne dla encji html wygląda następująco:

$htmlentity = "&(?:amp|apos|gt|lt|nbsp|quot|bull|hellip|[lr][ds]quo|[mn]dash|permil|\#[1-9][0-9]{1,3}|[A-Za-z][0-9A-Za-z]+);"

Po wyodrębnieniu (użyłem składni wąsów, aby to przedstawić), staje się nieco bardziej czytelny:

^(?:(?P<protocol>(?:ht|f)tps?|\w+(?=:\/\/))(?::\/\/))?
(?:(?P<host>(?:{{htmlentity}}|[^\/?#:])+(?::(?P<port>[0-9]+))?)\/)?
(?:(?P<path>(?:{{htmlentity}}|[^?#])+)\/)?
(?P<file>(?:{{htmlentity}}|[^?#])+)
(?:\?(?P<querystring>(?:{{htmlentity}};|[^#])+))?
(?:#(?P<fragment>.*))?$

Oczywiście w JavaScript nie można używać nazwanych odwołań wstecznych, więc wyrażenie regularne staje się

^(?:(\w+(?=:\/\/))(?::\/\/))?(?:((?:(?:&(?:amp|apos|gt|lt|nbsp|quot|bull|hellip|[lr][ds]quo|[mn]dash|permil|\#[1-9][0-9]{1,3}|[A-Za-z][0-9A-Za-z]+);)|[^\/?#:]+)(?::([0-9]+))?)\/)?(?:((?:(?:&(?:amp|apos|gt|lt|nbsp|quot|bull|hellip|[lr][ds]quo|[mn]dash|permil|\#[1-9][0-9]{1,3}|[A-Za-z][0-9A-Za-z]+);)|[^?#])+)\/)?((?:(?:&(?:amp|apos|gt|lt|nbsp|quot|bull|hellip|[lr][ds]quo|[mn]dash|permil|\#[1-9][0-9]{1,3}|[A-Za-z][0-9A-Za-z]+);)|[^?#])+)(?:\?((?:(?:&(?:amp|apos|gt|lt|nbsp|quot|bull|hellip|[lr][ds]quo|[mn]dash|permil|\#[1-9][0-9]{1,3}|[A-Za-z][0-9A-Za-z]+);)|[^#])+))?(?:#(.*))?$

iw każdym dopasowaniu protokołem jest \1host to \2, port \3, ścieżka \4, plik \5, kwerenda \6i fragment \7.

Steve K.
źródło
0
//USING REGEX
/**
 * Parse URL to get information
 *
 * @param   url     the URL string to parse
 * @return  parsed  the URL parsed or null
 */
var UrlParser = function (url) {
    "use strict";

    var regx = /^(((([^:\/#\?]+:)?(?:(\/\/)((?:(([^:@\/#\?]+)(?:\:([^:@\/#\?]+))?)@)?(([^:\/#\?\]\[]+|\[[^\/\]@#?]+\])(?:\:([0-9]+))?))?)?)?((\/?(?:[^\/\?#]+\/+)*)([^\?#]*)))?(\?[^#]+)?)(#.*)?/,
        matches = regx.exec(url),
        parser = null;

    if (null !== matches) {
        parser = {
            href              : matches[0],
            withoutHash       : matches[1],
            url               : matches[2],
            origin            : matches[3],
            protocol          : matches[4],
            protocolseparator : matches[5],
            credhost          : matches[6],
            cred              : matches[7],
            user              : matches[8],
            pass              : matches[9],
            host              : matches[10],
            hostname          : matches[11],
            port              : matches[12],
            pathname          : matches[13],
            segment1          : matches[14],
            segment2          : matches[15],
            search            : matches[16],
            hash              : matches[17]
        };
    }

    return parser;
};

var parsedURL=UrlParser(url);
console.log(parsedURL);
mohan mu
źródło
0

Wypróbowałem to wyrażenie regularne do analizowania partycji URL:

^((http[s]?|ftp):\/)?\/?([^:\/\s]+)(:([^\/]*))?((\/?(?:[^\/\?#]+\/+)*)([^\?#]*))(\?([^#]*))?(#(.*))?$

URL: https://www.google.com/my/path/sample/asd-dsa/this?key1=value1&key2=value2

Mecze:

Group 1.    0-7 https:/
Group 2.    0-5 https
Group 3.    8-22    www.google.com
Group 6.    22-50   /my/path/sample/asd-dsa/this
Group 7.    22-46   /my/path/sample/asd-dsa/
Group 8.    46-50   this
Group 9.    50-74   ?key1=value1&key2=value2
Group 10.   51-74   key1=value1&key2=value2
Bilal Demir
źródło
0

Ja buduję ten. Bardzo liberalne jest nie sprawdzanie adresu URL, tylko podzielenie go.

^((http[s]?):\/\/)?([a-zA-Z0-9-.]*)?([\/]?[^?#\n]*)?([?]?[^?#\n]*)?([#]?[^?#\n]*)$

  • dopasuj 1: pełny protokół z: // (http lub https)
  • dopasuj 2: protokół bez: //
  • mecz 3: host
  • mecz 4: ślimak
  • dopasuj 5: param
  • mecz 6: kotwica

praca

http://
https://
www.demo.com
/slug
?foo=bar
#anchor

https://demo.com
https://demo.com/
https://demo.com/slug
https://demo.com/slug/foo
https://demo.com/?foo=bar
https://demo.com/?foo=bar#anchor
https://demo.com/?foo=bar&bar=foo#anchor
https://www.greate-demo.com/

wypadek

#anchor#
?toto?
ZadzwońMarl
źródło
-2
String s = "https://www.thomas-bayer.com/axis2/services/BLZService?wsdl";

String regex = "(^http.?://)(.*?)([/\\?]{1,})(.*)";

System.out.println("1: " + s.replaceAll(regex, "$1"));
System.out.println("2: " + s.replaceAll(regex, "$2"));
System.out.println("3: " + s.replaceAll(regex, "$3"));
System.out.println("4: " + s.replaceAll(regex, "$4"));

Zapewni następujące dane wyjściowe:
1: https: //
2: www.thomas-bayer.com
3: /
4: axis2 / services / BLZService? Wsdl

Jeśli zmienisz adres URL na
String s = " https: //www.thomas -bayer.com?wsdl=qwerwer&ttt=888 "; wynik będzie następujący:
1: https: //
2: www.thomas-bayer.com
3 :?
4: wsdl = qwerwer & ttt = 888

ciesz się ..
Yosi Lev

ylev
źródło
Nie obsługuje portów. Czy nie jest agnostykiem językowym.
Ohgodwhy