Obtendo partes de um URL (Regex)


132

Dado o URL (linha única):
http://test.example.com/dir/subdir/file.html

Como posso extrair as seguintes partes usando expressões regulares:

  1. O subdomínio (teste)
  2. O domínio (exemplo.com)
  3. O caminho sem o arquivo (/ dir / subdir /)
  4. O arquivo (file.html)
  5. O caminho com o arquivo (/dir/subdir/file.html)
  6. O URL sem o caminho ( http://test.example.com )
  7. (adicione qualquer outro que considere útil)

A regex deve funcionar corretamente, mesmo se eu inserir o seguinte URL:

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

Esta não é uma resposta direta, mas a maioria das bibliotecas da web possui uma função que realiza essa tarefa. A função é freqüentemente chamada de algo semelhante a CrackUrl. Se essa função existir, use-a, é quase garantido que é mais confiável e mais eficiente do que qualquer código criado manualmente.
269 ​​Konrad Rudolph

7
Por favor, explique-nos por que isso precisa ser feito com uma regex. Se for lição de casa, diga isso porque essa é a sua restrição. Caso contrário, existem melhores soluções específicas de idioma do que usar um regex.
Andy Lester

1
Os links para a primeira e a última amostra estão quebrados.
o homem de lata

Aqui você pode encontrar como extrair esquema, domínio TLD, porto e localização da consulta: stackoverflow.com/questions/9760588/...
Paolo Rovelli

Respostas:


151

Um único regex para analisar e separar um URL completo, incluindo parâmetros de consulta e âncoras, por exemplo

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

Posições RexEx:

URL: RegExp ['$ &'],

protocolo: RegExp. $ 2,

host: RegExp. $ 3,

caminho: RegExp. $ 4,

arquivo: RegExp. $ 6,

consulta: RegExp. $ 7,

hash: RegExp. $ 8

você pode analisar ainda mais o host (delimitado por '.') com bastante facilidade.

O que eu faria é usar algo assim:

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

a análise adicional 'o resto' será o mais específica possível. Fazer isso em um regex é, bem, um pouco louco.


4
O link codesnippets.joyent.com/posts/show/523 não funciona a partir de 20 de outubro de
2010

19
O problema é esta parte: (.*)?como a estrela Kleene já aceita 0 ou mais, a ?parte (0 ou 1) a confunde. Corrigi-o mudando (.*)?para (.+)?. Você também pode simplesmente remover o?
rossipedia 25/10/10

3
Oi Dve, eu melhorei um pouco mais para extrair example.com de urls como http://www.example.com:8080/....Aqui vai:^((http[s]?|ftp):\/\/)?\/?([^\/\.]+\.)*?([^\/\.]+\.[^:\/\s\.]{2,3}(\.[^:\/\s\.]{2,3})?(:\d+)?)($|\/)([^#?\s]+)?(.*?)?(#[\w\-]+)?$
mnacos

4
ea prova de que não regexp é perfeito, aqui está uma correção imediata:^((http[s]?|ftp):\/\/)?\/?([^\/\.]+\.)*?([^\/\.]+\.[^:\/\s\.]{2,3}(\.[^:\/\s\.]{2,3})?)(:\d+)?($|\/)([^#?\s]+)?(.*?)?(#[\w\-]+)?$
mnacos

2
Eu modifiquei esta regex para identificar todas as partes do URL (versão melhorada) - código em Python ^((?P<scheme>[^:/?#]+):(?=//))?(//)?(((?P<login>[^:]+)(?::(?P<password>[^@]+)?)?@)?(?P<host>[^@/?#:]*)(?::(?P<port>\d+)?)?)?(?P<path>[^?#]*)(\?(?P<query>[^#]*))?(#(?P<fragment>.*))? code você mostra este código em ação no pythex.org
arannasousa

81

Sei que estou atrasado para a festa, mas existe uma maneira simples de permitir que o navegador analise um URL para você sem uma 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
Dado que a pergunta original foi marcada como "independente de idioma", que idioma é esse?
28414 MarkHu

observe que esta solução requer a existência de prefixo de protocolo, por exemplo http://, para exibição correta das propriedades de protocolo, host e nome de host. Caso contrário, o início do URL até a primeira barra vai para a propriedade de protocolo.
precisa

Acredito nisso, embora simples, mas muito mais lento que a análise do RegEx.
Demisx

É suportado por todos os navegadores?
Sean

1
Se estivermos indo por esse caminho, você também pode fazervar url = new URL(someUrl)
gman

67

Estou alguns anos atrasado para a festa, mas estou surpreso que ninguém tenha mencionado que a especificação do Uniform Resource Identifier possui uma seção sobre a análise de URIs com uma expressão regular . A expressão regular, escrita por Berners-Lee, et al., É:

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

Os números na segunda linha acima são apenas para ajudar na legibilidade; eles indicam os pontos de referência para cada subexpressão (ou seja, cada parêntese emparelhado). Nos referimos ao valor correspondente à subexpressão como $. Por exemplo, combinando a expressão acima com

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

resulta nas seguintes correspondências de subexpressão:

$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

Pelo que vale, descobri que tinha que escapar das barras no JavaScript:

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


4
Ótima resposta! Escolher algo de uma RFC pode certamente não ruim a coisa errada a fazer
frankster

1
isso não analisa os parâmetros de consulta
Rémy DAVID

2
Este é o melhor em conflito. Especificamente, isso aborda dois problemas que já vi com os outros 1:: Isso lida corretamente com outros protocolos, como ftp://e mailto://. 2: Isso lida corretamente com usernamee password. Esses campos opcionais são separados por dois pontos, assim como o nome do host e a porta, e ele disparará na maioria das outras expressões regulares que eu já vi. @ RémyDAVID A string de consulta também não é analisada normalmente pelo locationobjeto do navegador . Se você precisar analisar a string de consulta, dê uma olhada na minha pequena biblioteca para isso: uqs .
Stijn de Witt

2
Essa resposta merece mais votos, pois abrange praticamente todos os protocolos.
Tianzhen Lin

1
Ele quebra quando o protocolo está implícito HTTP com um nome de usuário / senha (uma sintaxe esotérica e tecnicamente inválido, admito) :, por exemplo user:pass@example.com- RFC 3986 diz: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

Achei que a resposta mais votada (resposta do hometoast) não funciona perfeitamente para mim. Dois problemas:

  1. Ele não pode lidar com o número da porta.
  2. A parte do hash está quebrada.

A seguir está uma versão modificada:

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

A posição das peças é a seguinte:

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

Edição publicada por um usuário anon:

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

1
Cuidado para não funcionar se o URL não tiver um caminho após o domínio - por exemplo, http://www.example.comou se o caminho tiver um único caractere http://www.example.com/a.
Fernando Correia

11

Eu precisava de uma expressão regular para corresponder a todos os URLs e fiz este:

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

Corresponde a todos os URLs, qualquer protocolo, até URLs como

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

O resultado (em JavaScript) fica assim:

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

Um URL como

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

se parece com isso:

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

3
Se você deseja combinar o domínio inteiro / endereço IP (não separado por pontos), use este:/(?:([^\:]*)\:\/\/)?(?:([^\:\@]*)(?:\:([^\@]*))?\@)?(?:([^\/\:]*))?(?:\:([0-9]*))?\/(\/[^\?#]*(?=.*?\/)\/)?([^\?#]*)?(?:\?([^#]*))?(?:#(.*))?/
lepe

11

Eu estava tentando resolver isso em javascript, que deve ser tratado por:

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

desde que (no Chrome, pelo menos) ele analisa:

{
  "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"
}

No entanto, este não é um navegador cruzado ( https://developer.mozilla.org/en-US/docs/Web/API/URL ), então juntei isso para extrair as mesmas partes acima:

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

O crédito para este regex vai para https://gist.github.com/rpflorence que postou este jsperf http://jsperf.com/url-parsing (originalmente encontrado aqui: https://gist.github.com/jlong/2428561 # comment-310066 ), que veio com o regex em que originalmente era baseado.

As peças estão nesta ordem:

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

Há também uma pequena biblioteca que a envolve e fornece parâmetros de consulta:

https://github.com/sadams/lite-url (também disponível no caramanchão)

Se você tiver uma melhoria, crie uma solicitação de recebimento com mais testes e aceitarei e mesclarei agradecimentos.


Isso é ótimo, mas poderia realmente ter uma versão como essa que extrai subdomínios em vez do host duplicado, nome do host. Então, se eu tivesse, http://test1.dev.mydomain.com/por exemplo, seria retirado test1.dev..
Lankymart

Isso funciona muito bem. Eu estava procurando uma maneira de extrair parâmetros de autenticação incomuns de URLs, e isso funciona muito bem.
21417 Aaron M

6

Propor uma solução muito mais legível (em Python, mas se aplica a qualquer 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')

Impressões:

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

5

subdomínio e domínio são difíceis porque o subdomínio pode ter várias partes, assim como o domínio de nível superior, 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 não é muito amigável para regexes)


2
Muito útil - eu adicionei um adicional (http(s?)://[^/]+/)para também pegar https
Mojowen 08/08

5

Esta versão aprimorada deve funcionar com tanta confiabilidade quanto um analisador.

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

Da minha resposta sobre uma pergunta semelhante . Funciona melhor do que alguns dos outros mencionados porque tinham alguns bugs (como não oferecer suporte a nome de usuário / senha, não oferecer suporte a nomes de arquivos de caractere único, identificadores de fragmentos sendo quebrados).


2

Você pode obter todos os http / https, host, porta, caminho e consulta usando o objeto Uri no .NET. apenas a tarefa difícil é dividir o host em subdomínio, nome de domínio e TLD.

Não existe um padrão para fazê-lo e não pode ser simplesmente usar a análise de string ou o RegEx para produzir o resultado correto. No começo, estou usando a função RegEx, mas nem todo URL pode analisar o subdomínio corretamente. A maneira prática é usar uma lista de TLDs. Depois que um TLD para um URL é definido, a parte esquerda é domínio e o restante é subdomínio.

No entanto, a lista precisa mantê-la, pois novos TLDs são possíveis. O momento atual que sei é publicsuffix.org manter a lista mais recente e você pode usar as ferramentas de domínio-analisador de código do google para analisar a lista de sufixos públicos e obter o subdomínio, domínio e TLD facilmente usando o objeto DomainName: domainName.SubDomain, domainName .Domain e domainName.TLD.

Essas respostas também são úteis: Obter o subdomínio de um URL

CaLLMeLaNN


2

Aqui está um que está completo e não depende de nenhum protocolo.

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

Impressões

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

Nenhuma das opções acima funcionou para mim. Aqui está o que eu acabei usando:

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

2

Eu gosto da regex publicada em "Javascript: The Good Parts". Não é muito curto nem muito complexo. Esta página no github também possui o código JavaScript que a utiliza. Mas pode ser adaptado para qualquer idioma. https://gist.github.com/voodooGQ/4057330


1

Java oferece uma classe de URL que fará isso. Objetos de URL de consulta.

Em uma nota lateral, o PHP oferece parse_url () .


Parece que isso não analisa o subdomínio?
precisa saber é o seguinte

Asker pediu regex. A classe de URL abrirá uma conexão quando você a criar.
MikeNereson

"A classe URL abrirá uma conexão quando você a criar" - isso é incorreto, apenas quando você chama métodos como connect (). Mas é verdade que o java.net.URL é um pouco pesado. Nesse caso de uso, o java.net.URI é melhor.
Jcsahnwaldt Restabelecer Monica


1

Eu tentei alguns deles que não atendiam às minhas necessidades, especialmente os mais votados que não capturavam um URL sem um caminho ( http://example.com/ )

também a falta de nomes de grupos tornou inutilizável em ansible (ou talvez minhas habilidades jinja2 estejam faltando).

então esta é minha versão ligeiramente modificada, com a fonte sendo a versão mais votada aqui:

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

0

Usando http://www.fileformat.info/tool/regex.htm, o regex do hometoast funciona muito bem.

Mas aqui está o acordo: quero usar diferentes padrões de regex em diferentes situações do meu programa.

Por exemplo, eu tenho esse URL e uma enumeração que lista todos os URLs suportados no meu programa. Cada objeto na enumeração possui um método getRegexPattern que retorna o padrão de expressão regular que será usado para comparar com uma URL. Se o padrão específico de regex retornar true, eu sei que esse URL é suportado pelo meu programa. Portanto, cada enumeração possui seu próprio regex, dependendo de onde deve procurar dentro da URL.

A sugestão do Hometoast é ótima, mas no meu caso, acho que não ajudaria (a menos que copie e cole o mesmo regex em todas as enumerações).

É por isso que eu queria que a resposta desse regex para cada situação separadamente. Embora +1 para hometoast. ;)


0

Sei que você está afirmando que não tem linguagem, mas pode nos dizer o que está usando, para sabermos quais recursos de regex você possui?

Se você possui os recursos para correspondências que não capturam, é possível modificar a expressão do hometoast para que as subexpressões que você não está interessado em capturar sejam configuradas da seguinte forma:

(?:SOMESTUFF)

Você ainda teria que copiar e colar (e modificar levemente) o Regex em vários lugares, mas isso faz sentido - você não está apenas verificando se a subexpressão existe, mas se existe como parte de uma URL . Usar o modificador de não captura para subexpressões pode fornecer o que você precisa e nada mais, o que, se eu estiver lendo você corretamente, é o que você deseja.

Assim como uma nota pequena e pequena, a expressão do hometoast não precisa colocar colchetes ao redor do 's' para 'https', pois ele tem apenas um caractere. Os quantificadores quantificam o único caractere (ou classe ou subexpressão de caracteres) que os precede diretamente. Assim:

https?

corresponderia a 'http' ou 'https' muito bem.


0

regexp para obter o caminho da URL sem o arquivo

url = ' http: // domínio / dir1 / dir2 / algum arquivo' url.scan (/ ^ (http: // [^ /] +) ((?: / [^ /] +) + (? = /)) ? /? (?: [^ /] +)? $ / i) .to_s

Pode ser útil para adicionar um caminho relativo a este URL.


0

O regex para fazer a análise completa é bastante horrendo. Incluí referências de referência nomeadas para legibilidade e dividi cada parte em linhas separadas, mas ainda assim é assim:

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

O que exige que seja tão detalhado é que, exceto pelo protocolo ou pela porta, qualquer uma das partes pode conter entidades HTML, o que torna bastante complicado o delineamento do fragmento. Portanto, nos últimos casos - host, caminho, arquivo, string de consulta e fragmento, permitimos qualquer entidade html ou caractere que não seja um ?ou #. O regex para uma entidade html se parece com isso:

$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 isso é extraído (usei uma sintaxe de bigode para representá-lo), ele se torna um pouco mais legível:

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

No JavaScript, é claro, você não pode usar referências anteriores nomeadas, portanto, a regex se torna

^(?:(\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 em cada correspondência, o protocolo é \1o host \2, a porta \3, o caminho \4, o arquivo \5, a cadeia de consulta \6e o fragmento \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

Eu tentei este regex para analisar partições de URL:

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

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

Partidas:

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

Fornecerá a seguinte saída:
1: https: //
2: www.thomas-bayer.com
3: /
4: axis2 / services / BLZService? Wsdl

Se você alterar o URL para
String s = " https: //www.thomas -bayer.com?wsdl=qwerwer&ttt=888 "; a saída será a seguinte:
1: https: //
2: www.thomas-bayer.com
3:?
4: wsdl = qwerwer & ttt = 888

aproveite ..
Yosi Lev


Não lida com portas. A linguagem não é independente.
Ohgodwhy
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.