Expresión regular para detenerse en el primer partido

532

Mi patrón de expresiones regulares se parece a

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

Solo me interesa la parte de las cotizaciones asignadas a la ubicación. ¿No debería ser tan fácil como a continuación sin el codicioso interruptor?

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

No parece funcionar

publicRavi
fuente
¿Cuál es su fuente, es HTML o XML o algo así?
Oskar Kjellin
20
¿Por qué es una wiki comunitaria? Es una pregunta real. Muy tarde ahora.
Ahmad Mageed
1
¿En qué idioma estás escribiendo? Por favor, no use expresiones regulares para XML. Hay muchas maneras mejores de analizar XML
Oskar Kjellin el
3
No, si todo lo que quiere es buscar atributos simples. Regex es apropiado y más rápido.
Codenheim
Diría que si, por ejemplo, codifica c #, es mucho mejor usar linq para esto. Dudo que sea mejor regex si tienes un buen analizador
Oskar Kjellin

Respuestas:

1097

Debe hacer que su expresión regular no sea codiciosa, ya que de forma predeterminada "(.*)"coincidirá con todos"file path/level1/level2" xxx some="xxx" .

En cambio, puede hacer que su estrella de punto no sea codiciosa, lo que hará que coincida con la menor cantidad de caracteres posible:

/location="(.*?)"/

Agregar ?a un cuantificador ( ?, *o +) lo hace no codicioso.

Daniel Vandersluis
fuente
32
FWIW, en caso de que uses VIM, esta expresión regular debe ser un poco diferente: en lugar de .*?ser .\{-}para una coincidencia no codiciosa.
SooDesuNe
44
Gracias Daniel "Agregar un? En un cuantificador (?, * O +) hace que no sea codicioso". Es un consejo útil para mí.
PhatHV
10
Los ? describe mi confusión al tratar de resolver esto. Que apropiado.
Robbie Smith
1
Creo que puedes decir 'perezoso' en lugar de 'no codicioso'
Manticore
50

location="(.*)"coincidirá desde el "después location=hasta el" después, a some="xxxmenos que lo haga no codicioso. Por lo tanto, usted necesita .*?(es decir, hacerlo no codicioso) o mejor reemplazarlo .*con [^"]*.

sepp2k
fuente
3
[^ "] * también es probablemente más rápido con la mayoría de los motores regex porque no necesita buscar el patrón después del patrón actual.
Jean Vincent
1
@Kip: Probablemente tengas razón, pero la .*?notación es más general que[^"]*
Bondax
¿qué tal si quiero incluir el carácter delimitador usando [^ "] *
Frohlich
para nada, si no sabes lo que ^ y [] significan aquí. La mayoría de la gente lo entenderá. *
Vincent Gerris
31

Qué tal si

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

Esto evita la búsqueda ilimitada con. * Y coincidirá exactamente con la primera cita.

usuario193690
fuente
Debido a las discrepancias en grep, lo anterior debería ser el patrón preferido si la portabilidad es una preocupación.
Josh Habdas
22

Utilice la coincidencia no codiciosa, si su motor lo admite. Añade el ? dentro de la captura.

/location="(.*?)"/
Codenheim
fuente
11

El uso de cuantificadores perezosos ?sin bandera global es la respuesta.

P.ej,

ingrese la descripción de la imagen aquí

Si tuviera una bandera global /gentonces, habría coincidido con todas las coincidencias de menor longitud como se muestra a continuación. ingrese la descripción de la imagen aquí

Uddhav Gautam
fuente
1

Porque estas usando subpatrón cuantificado y como se describe en Perl Doc ,

De manera predeterminada, un subpatrón cuantificado es " codicioso ", es decir, coincidirá tantas veces como sea posible (dada una ubicación de inicio particular) mientras permite que el resto del patrón coincida. Si desea que coincida con el número mínimo de veces posible, siga el cuantificador con un "?" . Tenga en cuenta que los significados no cambian, solo la "codicia":

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

Por lo tanto, para permitir que su patrón cuantificado haga una coincidencia mínima, sígalo ?:

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

Aquí hay otra forma.

Aquí está el que quieres. Esto es vago[\s\S]*?

El primer elemento: [\s\S]*?(?:location="[^"]*")[\s\S]* reemplazar con:$1

Explicación : https://regex101.com/r/ZcqcUm/2


Para completar, esto obtiene el último. Esto es codicioso[\s\S]*

El último elemento:[\s\S]*(?:location="([^"]*)")[\s\S]* reemplazar con:$1

Explicación : https://regex101.com/r/LXSPDp/3


Solo hay 1 diferencia entre estas dos expresiones regulares y esa es la ?

Stephen Sherry
fuente