Ottenere parti di un URL (Regex)


132

Dato l'URL (riga singola):
http://test.example.com/dir/subdir/file.html

Come posso estrarre le seguenti parti usando le espressioni regolari:

  1. Il sottodominio (test)
  2. Il dominio (esempio.com)
  3. Il percorso senza il file (/ dir / subdir /)
  4. Il file (file.html)
  5. Il percorso con il file (/dir/subdir/file.html)
  6. L'URL senza il percorso ( http://test.example.com )
  7. (aggiungi qualsiasi altro che ritieni possa essere utile)

Il regex dovrebbe funzionare correttamente anche se inserisco il seguente URL:

http://example.example.com/example/example/example.html

Questa non è una risposta diretta ma la maggior parte delle librerie Web ha una funzione che svolge questo compito. La funzione viene spesso chiamata qualcosa di simile a CrackUrl. Se esiste una tale funzione, usala, è quasi garantita che sia più affidabile e più efficiente di qualsiasi codice realizzato a mano.
Konrad Rudolph,

7
Per favore, spiegaci perché questo deve essere fatto con una regex. Se sono i compiti, allora dillo perché questo è il tuo vincolo. Altrimenti, ci sono soluzioni specifiche per la lingua migliori rispetto all'uso di una regex.
Andy Lester,

1
I collegamenti al primo e all'ultimo campione sono interrotti.
Tin Man,

Qui puoi trovare come estrarre schema, dominio, TLD, porta e percorso della query: stackoverflow.com/questions/9760588/…
Paolo Rovelli

Risposte:


151

Una singola regex per analizzare e suddividere un URL completo, inclusi parametri di query e ancore, ad es

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\-]+)?$

Posizioni RexEx:

url: RegExp ['$ &'],

protocollo:. RegExp $ 2,

host:. RegExp $ 3,

percorso:. RegExp $ 4,

File:. RegExp $ 6,

query:. RegExp $ 7,

hash:. RegExp $ 8

potresti quindi analizzare ulteriormente l'host ('.' delimitato) abbastanza facilmente.

Quello che vorrei fare è usare qualcosa del genere:

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

l'ulteriore analisi "il resto" deve essere il più specifico possibile. Farlo in una regex è, beh, un po 'pazzo.


4
Il link codesnippets.joyent.com/posts/show/523 non funziona dal 20 ottobre 10
W3 Max

19
Il problema è questa parte: (.*)?poiché la stella Kleene accetta già 0 o più, la ?parte (0 o 1) la confonde. L'ho risolto cambiando (.*)?in (.+)?. Puoi anche rimuovere il?
rossipedia il

3
Ciao Dve, l'ho migliorato un po 'di più per estrarre example.com dagli URL come http://www.example.com:8080/....Here ^((http[s]?|ftp):\/\/)?\/?([^\/\.]+\.)*?([^\/\.]+\.[^:\/\s\.]{2,3}(\.[^:\/\s\.]{2,3})?(:\d+)?)($|\/)([^#?\s]+)?(.*?)?(#[\w\-]+)?$
going

4
e prova che nessuna regexp è perfetta, ecco una correzione immediata:^((http[s]?|ftp):\/\/)?\/?([^\/\.]+\.)*?([^\/\.]+\.[^:\/\s\.]{2,3}(\.[^:\/\s\.]{2,3})?)(:\d+)?($|\/)([^#?\s]+)?(.*?)?(#[\w\-]+)?$
mnacos,

2
Ho modificato questo regex per identificare tutte le parti dell'URL (versione migliorata) - codice in Python Mostrate^((?P<scheme>[^:/?#]+):(?=//))?(//)?(((?P<login>[^:]+)(?::(?P<password>[^@]+)?)?@)?(?P<host>[^@/?#:]*)(?::(?P<port>\d+)?)?)?(?P<path>[^?#]*)(\?(?P<query>[^#]*))?(#(?P<fragment>.*))? code questo codice in azione su pythex.org
arannasousa

81

Mi rendo conto di essere in ritardo alla festa, ma esiste un modo semplice per consentire al browser di analizzarti un URL senza una regex:

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
*/

9
Dato che la domanda originale era taggata "lingua-agnostica", che lingua è questa?
MarkHu,

si noti che questa soluzione richiede l'esistenza di un prefisso di protocollo, ad esempio http://, per la corretta visualizzazione delle proprietà di protocollo, host e nome host. Altrimenti l'inizio dell'URL fino alla prima barra passa alla proprietà del protocollo.
Oleksii Aza,

Credo che questo, sebbene semplice, ma molto più lento dell'analisi RegEx.
Demisx,

È supportato da tutti i browser?
sean,

1
Se stiamo andando in questo modo puoi anche farlovar url = new URL(someUrl)
Gman,

67

Sono in ritardo di qualche anno alla festa, ma sono sorpreso che nessuno abbia menzionato la specifica dell'identificatore di risorsa uniforme che contiene una sezione sull'analisi degli URI con un'espressione regolare . L'espressione regolare, scritta da Berners-Lee, et al., È:

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

I numeri nella seconda riga sopra sono solo per aiutare la leggibilità; indicano i punti di riferimento per ciascuna sottoespressione (cioè ogni parentesi accoppiata). Ci riferiamo al valore corrispondente per la sottoespressione come $. Ad esempio, abbinando l'espressione sopra a

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

risulta nelle seguenti corrispondenze di sottoespressione:

$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

Per quello che vale, ho scoperto che dovevo sfuggire alle barre in avanti in JavaScript:

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


4
Bella risposta! La scelta di qualcosa da un RFC può sicuramente mai male la cosa sbagliata da fare
Frankster

1
questo non analizza i parametri della query
Rémy DAVID

2
Questo è il migliore afaict. Nello specifico questo risolve due problemi che ho riscontrato con gli altri 1:: Questo si occupa correttamente di altri protocolli, come ftp://e mailto://. 2: Si occupa correttamente di usernamee password. Questi campi opzionali sono separati da due punti, proprio come il nome host e la porta, e farà scattare la maggior parte delle altre regex che ho visto. @ RémyDAVID Anche la querystring non viene analizzata normalmente locationdall'oggetto browser . Se devi analizzare la stringa di query, dai un'occhiata alla mia piccola libreria per questo: uqs .
Stijn de Witt,

2
Questa risposta merita più voti perché copre praticamente tutti i protocolli.
Tianzhen Lin,

1
Si interrompe quando il protocollo è implicito HTTP con un nome utente / password (una sintassi esoterica e tecnicamente non valida, lo ammetto) :, ad es. user:pass@example.com- RFC 3986 dice: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

Ho trovato la risposta più votata (la risposta di hometoast) non funziona perfettamente per me. Due problemi:

  1. Non può gestire il numero di porta.
  2. La parte hash è rotta.

La seguente è una versione modificata:

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

La posizione delle parti è la seguente:

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

Modifica pubblicata da un altro utente:

function getFileName(path) {
    return path.match(/^((http[s]?|ftp):\/)?\/?([^:\/\s]+)(:([^\/]*))?((\/[\w\/-]+)*\/)([\w\-\.]+[^#?\s]+)(\?([^#]*))?(#(.*))?$/i)[8];
}

1
Attenzione che non funziona se l'URL non ha un percorso dopo il dominio, ad esempio http://www.example.como se il percorso è un singolo carattere come http://www.example.com/a.
Fernando Correia,

11

Avevo bisogno di un'espressione regolare per abbinare tutti gli URL e ho creato questo:

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

Corrisponde a tutti gli URL, a qualsiasi protocollo, persino agli URL come

ftp://user:pass@www.cs.server.com:8080/dir1/dir2/file.php?param1=value1#hashtag

Il risultato (in JavaScript) è simile al seguente:

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

Un url come

mailto://admin@www.cs.server.com

Somiglia a questo:

["mailto", "admin", undefined, "www.cs", "server", "com", undefined, undefined, undefined, undefined, undefined] 

3
Se vuoi abbinare l'intero dominio / indirizzo IP (non separato da punti) usa questo:/(?:([^\:]*)\:\/\/)?(?:([^\:\@]*)(?:\:([^\@]*))?\@)?(?:([^\/\:]*))?(?:\:([0-9]*))?\/(\/[^\?#]*(?=.*?\/)\/)?([^\?#]*)?(?:\?([^#]*))?(?:#(.*))?/
lepe

11

Stavo cercando di risolverlo in javascript, che dovrebbe essere gestito da:

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

poiché (almeno in Chrome) analizza:

{
  "hash": "#foobar/bing/bo@ng?bang",
  "search": "?foo=bar&bingobang=&king=kong@kong.com",
  "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:b@example.com:890/path/wah@t/foo.js?foo=bar&bingobang=&king=kong@kong.com#foobar/bing/bo@ng?bang"
}

Tuttavia, questo non è cross-browser ( https://developer.mozilla.org/en-US/docs/Web/API/URL ), quindi l'ho messo insieme per estrarre le stesse parti come sopra:

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

Il merito di questo regex va a https://gist.github.com/rpflorence che ha pubblicato questo jsperf http://jsperf.com/url-parsing (originariamente trovato qui: https://gist.github.com/jlong/2428561 # comment-310066 ) che ha inventato la regex su cui era originariamente basato.

Le parti sono in questo ordine:

var keys = [
    "href",                    // http://user:pass@host.com:81/directory/file.ext?query=1#anchor
    "origin",                  // http://user:pass@host.com: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
];

C'è anche una piccola libreria che la avvolge e fornisce parametri di query:

https://github.com/sadams/lite-url (disponibile anche su pergolato)

Se hai un miglioramento, crea una richiesta pull con più test e accetterò e unirò con ringraziamenti.


Questo è fantastico, ma potrebbe davvero fare con una versione come questa che estrae i sottodomini invece dell'host duplicato, nome host. Quindi, se avessi http://test1.dev.mydomain.com/ad esempio, si tirerebbe fuori test1.dev..
Lankymart,

Funziona molto bene Ho cercato un modo per estrarre parametri URL insoliti dagli URL, e questo funziona magnificamente.
Aaron M

6

Proponi una soluzione molto più leggibile (in Python, ma si applica a qualsiasi regex):

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')

stampe:

{
'host': 'example.example.com', 
'user': None, 
'path': '/example/example/example.html', 
'query': None, 
'password': None, 
'port': None, 
'schema': 'http'
}

5

sottodominio e dominio sono difficili perché il sottodominio può avere diverse parti, così come il dominio di primo livello, 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 non è molto amichevole con le regex)


2
Molto utile - Ho aggiunto un ulteriore (http(s?)://[^/]+/)per prendere anche https
Mojowen

5

Questa versione migliorata dovrebbe funzionare in modo affidabile come un 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'
   }


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>#(.*))?$/

Dalla mia risposta a una domanda simile . Funziona meglio di alcuni degli altri citati perché avevano alcuni bug (come non supportare nome utente / password, non supportare nomi di file a carattere singolo, identificatori di frammenti rotti).


2

È possibile ottenere tutti gli http / https, host, porta, percorso e query utilizzando l'oggetto Uri in .NET. solo il compito difficile è quello di suddividere l'host in sottodominio, nome di dominio e TLD.

Non esiste uno standard per farlo e non può essere semplicemente utilizzare l'analisi delle stringhe o RegEx per produrre il risultato corretto. All'inizio sto usando la funzione RegEx ma non tutti gli URL possono analizzare correttamente il sottodominio. Il modo pratico è utilizzare un elenco di TLD. Dopo aver definito un TLD per un URL, la parte sinistra è dominio e il restante è sottodominio.

Tuttavia l'elenco deve mantenerlo poiché sono possibili nuovi TLD. Il momento attuale che conosco è publicsuffix.org per mantenere l'elenco più recente e puoi usare gli strumenti domain parser dal dominio di Google per analizzare l'elenco dei suffissi pubblici e ottenere facilmente il sottodominio, il dominio e il TLD usando l'oggetto DomainName: domainName.SubDomain, domainName .Domain e domainName.TLD.

Ciò risponde anche utile: Ottieni il sottodominio da un URL

CaLLMeLaNN


2

Eccone uno completo e non si basa su alcun protocollo.

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")

stampe

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

2

Nessuna delle precedenti ha funzionato per me. Ecco cosa ho finito per usare:

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

2

Mi piace il regex che è stato pubblicato in "Javascript: The Good Parts". Non è troppo corto e non troppo complesso. Questa pagina su github ha anche il codice JavaScript che la utilizza. Ma può essere adattato per qualsiasi lingua. https://gist.github.com/voodooGQ/4057330


1

Java offre una classe URL che lo farà. Interroga oggetti URL.

Come nota a margine , PHP offre parse_url () .


Sembra che questo non analizzi il sottodominio però?
Chris Dutrow,

Asker ha chiesto regex. La classe URL aprirà una connessione quando la crei.
MikeNereson,

"La classe URL aprirà una connessione quando la crei" - non è corretto, solo quando chiami metodi come connect (). Ma è vero che java.net.URL è piuttosto pesante. Per questo caso d'uso, java.net.URI è migliore.
jcsahnwaldt Reinstate Monica


1

Ho provato alcuni di questi che non soddisfano le mie esigenze, in particolare i più votati che non hanno catturato un url senza percorso ( http://esempio.com/ )

anche la mancanza di nomi di gruppo lo rendeva inutilizzabile in ansible (o forse mancano le mie abilità di jinja2).

quindi questa è la mia versione leggermente modificata con la fonte essendo la versione più votata qui:

^((?P<protocol>http[s]?|ftp):\/)?\/?(?P<host>[^:\/\s]+)(?P<path>((\/\w+)*\/)([\w\-\.]+[^#?\s]+))*(.*)?(#[\w\-]+)?$

0

Utilizzando http://www.fileformat.info/tool/regex.htm regex di hometoast funziona alla grande.

Ma ecco il problema, voglio usare diversi schemi regex in diverse situazioni del mio programma.

Ad esempio, ho questo URL e ho un elenco che elenca tutti gli URL supportati nel mio programma. Ogni oggetto nell'enumerazione ha un metodo getRegexPattern che restituisce il modello regex che verrà quindi utilizzato per confrontare con un URL. Se il particolare modello regex ritorna vero, allora so che questo URL è supportato dal mio programma. Quindi, ogni enumerazione ha la propria regex a seconda di dove dovrebbe apparire all'interno dell'URL.

Il suggerimento di Hometoast è eccezionale, ma nel mio caso, penso che non sarebbe di aiuto (a meno che non copi incolla la stessa regex in tutte le enumerazioni).

Ecco perché volevo che la risposta desse la regex per ogni situazione separatamente. Anche se +1 per l'hometoast. ;)


0

So che stai rivendicando il linguaggio agnostico su questo, ma puoi dirci cosa stai usando solo per sapere quali funzionalità regex hai?

Se disponi delle funzionalità per le partite non acquisite, puoi modificare l'espressione di hometoast in modo che le sottoespressioni che non ti interessano catturare siano impostate in questo modo:

(?:SOMESTUFF)

Dovresti comunque copiare e incollare (e modificare leggermente) il Regex in più punti, ma questo ha senso: non stai solo verificando se la sottoespressione esiste, ma piuttosto se esiste come parte di un URL . L'uso del modificatore non di acquisizione per le sottoespressioni può darti ciò di cui hai bisogno e niente di più, che, se ti sto leggendo correttamente, è quello che vuoi.

Proprio come una piccola nota, l'espressione di hometoast non ha bisogno di mettere parentesi attorno alla 's' per 'https', poiché ha solo un carattere. I quantificatori quantificano l'unico carattere (o classe di caratteri o sottoespressione) che li precede direttamente. Così:

https?

corrisponderebbe perfettamente a "http" o "https".


0

regexp per ottenere il percorso URL senza il file.

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

Può essere utile per aggiungere un percorso relativo a questo URL.


0

La regex per eseguire l'analisi completa è abbastanza orrenda. Ho incluso backreferences nominati per leggibilità e ho suddiviso ogni parte in righe separate, ma sembra ancora così:

^(?:(?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>.*))?$

La cosa che richiede che sia così prolisso è che, tranne per il protocollo o la porta, una qualsiasi delle parti può contenere entità HTML, il che rende la delineazione del frammento piuttosto complicata. Quindi negli ultimi casi - l'host, il percorso, il file, la stringa di query e il frammento, consentiamo qualsiasi entità html o qualsiasi carattere che non sia un ?o #. La regex per un'entità html è simile alla seguente:

$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]+);"

Quando viene estratto (ho usato una sintassi dei baffi per rappresentarlo), diventa un po 'più leggibile:

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

In JavaScript, ovviamente, non puoi usare backreferences nominati, quindi la regex diventa

^(?:(\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]+);)|[^#])+))?(?:#(.*))?$

e in ogni corrispondenza, il protocollo è \1, l'host è \2, la porta è \3, il percorso \4, il file \5, la stringa di query \6e il frammento \7.


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);

0

Ho provato questo regex per l'analisi delle partizioni url:

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

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

gli incontri:

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

-1
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"));

Fornirà il seguente output:
1: https: //
2: www.thomas-bayer.com
3: /
4: axis2 / services / BLZService? Wsdl

Se si modifica l'URL in
String s = " https: //www.thomas -bayer.com?wsdl=qwerwer&ttt=888 "; l'output sarà il seguente:
1: https: //
2: www.thomas-bayer.com
3 :?
4: wsdl = qwerwer & ttt = 888

buon divertimento ..
Yosi Lev


Non gestisce le porte. La lingua non è agnostica.
Ohgodwhy,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.