Expressão regular para parar na primeira partida

531

Meu padrão regex se parece com

<xxxx location="file path/level1/level2" xxxx some="xxx">

Estou interessado apenas na parte entre aspas atribuídas ao local. Não deveria ser tão fácil como abaixo sem a opção gananciosa?

/.*location="(.*)".*/

Não parece funcionar.

público
fonte
Qual é a sua fonte, é HTML ou xml ou algo assim?
Oskar Kjellin
20
Por que este é um wiki da comunidade? É uma pergunta real. Tarde demais agora.
Ahmad Mageed 23/03/10
1
Em que idioma você está escrevendo? Por favor, não use regex para XML. Existem tantas maneiras melhores de analisar XML
Oskar Kjellin 23/03
3
Não, se tudo o que você deseja é procurar atributos simples. Regex é apropriado e mais rápido.
Codenheim
Eu diria que, se você por exemplo codificar c #, é muito melhor usar o linq para isso. Eu duvido que ele vai ser melhor para regex se você tiver um bom analisador
Oskar Kjellin

Respostas:

1096

Você precisa tornar sua expressão regular não ambiciosa, porque, por padrão, "(.*)"corresponderá a todos "file path/level1/level2" xxx some="xxx".

Em vez disso, você pode tornar sua estrela de ponto não gananciosa, o que fará com que ele corresponda ao mínimo de caracteres possível:

/location="(.*?)"/

Adicionando a ?em um quantificador (? , *ou +) torna-o não ganancioso.

Daniel Vandersluis
fonte
32
FWIW, caso você use o VIM, esse regex precisa ser um pouco diferente: em vez de .*?ser .\{-}para uma correspondência não gananciosa.
SooDesuNe 24/03
44
Obrigado Daniel. "Adicionar um? Em um quantificador (?, * Ou +) torna-o não ganancioso." é uma dica útil para mim.
PhatHV
10
O ? descreve minha confusão ao tentar descobrir isso. Quão apropriado.
22616 Robbie Smith
1
Eu acredito que você pode dizer 'preguiçoso' em vez de 'não-ganancioso'
Manticore
50

location="(.*)"corresponderá do "depois location=até o" depois, a some="xxxmenos que você o torne não ganancioso. Então você precisa .*?(ou seja, não seja ganancioso) ou melhor substitui-o .*por [^"]*.

sepp2k
fonte
3
[^ "] * Também é provavelmente mais rápido com a maioria dos motores regex porque ele não precisa procurar o padrão após o padrão atual.
Jean Vincent
1
@Kip: Você provavelmente está certo, mas a .*?notação é mais geral do que[^"]*
Bondax
como sobre se eu quiser incluir o caractere delimitador usando [^ "] *
Frohlich
de maneira alguma, se você não sabe o que ^ e [] significam aqui. A maioria das pessoas entenderá. *
Vincent Gerris
31

E se

.*location="([^"]*)".*

Isso evita a pesquisa ilimitada com. * E corresponderá exatamente à primeira cotação.

user193690
fonte
Devido a discrepâncias no grep, o padrão acima deve ser o preferido se a portabilidade for uma preocupação.
Josh Habdas
22

Use correspondência não gananciosa, se o seu mecanismo suportar. Adicione o ? dentro da captura.

/location="(.*?)"/
codenheim
fonte
11

O uso de quantificadores preguiçosos ?sem bandeira global é a resposta.

Por exemplo,

insira a descrição da imagem aqui

Se você tivesse uma bandeira global /g, ela corresponderia a todas as correspondências de menor comprimento, conforme abaixo. insira a descrição da imagem aqui

Uddhav Gautam
fonte
1

Como você está usando sub - padrão quantificado e conforme descrito no Perl Doc ,

Por padrão, um sub-padrão quantificado é " ganancioso ", ou seja, corresponderá o maior número de vezes possível (dado um local de partida específico), enquanto ainda permite que o restante do padrão seja correspondido. Se você deseja que ele corresponda ao número mínimo de vezes possível, siga o quantificador com um "?" . Note que os significados não mudam, apenas a "ganância":

*?        //Match 0 or more times, not greedily (minimum matches)
+?        //Match 1 or more times, not greedily

Portanto, para permitir que seu padrão quantificado faça a correspondência mínima, siga-o ?:

/location="(.*?)"/
Mohammad Kanan
fonte
1

Aqui está outra maneira.

Aqui está o que você deseja. Isso é preguiçoso[\s\S]*?

O primeiro item: [\s\S]*?(?:location="[^"]*")[\s\S]* Substitua por:$1

Explicação : https://regex101.com/r/ZcqcUm/2


Para ser completo, esse é o último. Isso é ganancioso[\s\S]*

O último item:[\s\S]*(?:location="([^"]*)")[\s\S]* Substitua por:$1

Explicação : https://regex101.com/r/LXSPDp/3


Há apenas uma diferença entre essas duas expressões regulares e esse é o ?

Stephen Sherry
fonte