Expresión regular para detenerse en la primera coincidencia

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 asignada a la ubicación. ¿No debería ser tan fácil como a continuación sin el codicioso interruptor?

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

No parece funcionar.

preguntado el 23 de marzo de 10 a las 17:03

¿Cuál es tu fuente, es HTML o xml o algo así? -

¿Por qué es esta una wiki comunitaria? Es una pregunta real. Muy tarde ahora. -

¿En qué idioma estás escribiendo? No utilice expresiones regulares para XML. Hay muchas formas mejores de analizar XML:

No si todo lo que desea es buscar atributos simples. Regex es apropiado y más rápido. -

Yo diría que si, por ejemplo, codificas c #, es mucho mejor usar linq para esto. Dudo que sea mejor usar expresiones regulares si tienes un buen analizador -

9 Respuestas

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

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

/location="(.*?)"/

Añadiendo un ? en un cuantificador?, * or +) lo hace no codicioso.

respondido 23 mar '10, 20:03

FWIW, en caso de que esté usando VIM, esta expresión regular debe ser un poco diferente: en lugar de .*? es .\{-} para un partido no codicioso. - SooDesuNe

Gracias Daniel "Agregar un? En un cuantificador (?, * O +) lo hace no codicioso". es un consejo útil para mí. - PhatHV

La ? describe mi confusión al tratar de resolver esto. Qué apropiado. - robbie smith

Creo que puedes decir 'vago' en lugar de 'no codicioso' - Manticore

Debido a que la pregunta no especifica un dialecto de expresiones regulares en particular, esta respuesta debe especificar que solo está disponible en motores de expresiones regulares que implementan las extensiones de Perl 5 (Java, Ruby, Python, etc.) pero no en motores de expresiones regulares "tradicionales" (incluido JavaScript , Awk, sed, grep sin -P, etc.). - triples

location="(.*)" coincidirá con el "después location= hasta el "después some="xxx a menos que lo hagas no codicioso. Entonces o necesitas .*? (es decir, que no sea codicioso) o mejor reemplácelo .* con [^"]*.

respondido 23 mar '10, 20:03

[^ "] * también es probablemente más rápido con la mayoría de los motores de expresiones regulares porque no necesita buscar el patrón después del patrón actual. Juan Vicente

@Kip: Probablemente tengas razón, pero el .*? la notación es más general que [^"]* - Bondax

¿qué tal si quiero incluir el carácter delimitador usando [^ "] * - Fróhlich

en absoluto, si no sabe lo que ^ y [] significan aquí. La mayoría de la gente lo entenderá. * - vicente gerris

¿Qué tal

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

Esto evita la búsqueda ilimitada con. * Y coincidirá exactamente con la primera cotización.

Respondido 21 Feb 13, 08:02

Debido a el discrepancias en grep lo anterior debería ser el patrón preferido si la portabilidad es un problema. - jose hadas

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

/location="(.*?)"/

respondido 23 mar '10, 20:03

Uso de cuantificadores perezosos ? sin bandera global es la respuesta.

P.ej,

enter image description here

Si tuvieras bandera global /g entonces, habría coincidido con todas las coincidencias de longitud más baja como se muestra a continuación. enter image description here

Respondido 24 Jul 18, 02:07

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

De forma predeterminada, un subpatrón cuantificado es "codicioso", es decir, coincidirá con muchas veces como sea posible (dada una ubicación de inicio particular) sin dejar de permitir que el resto del patrón coincida. Si lo quieres para que coincida con el número mínimo de veces posible, siga el cuantificador con a "?" . 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 cuantificado patrón para hacer una coincidencia mínima, sígalo por ? :

/location="(.*?)"/

respondido 20 nov., 18:10

He aquí otra forma.

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

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

Explicacion: https://regex101.com/r/ZcqcUm/2


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

El último artículo:[\s\S]*(?:location="([^"]*)")[\s\S]* Reemplazar con: $1

Explicacion: https://regex101.com/r/LXSPDp/3


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

respondido 30 nov., 19:12

Las otras respuestas aquí no explican una solución completa para las versiones de expresiones regulares que no admiten la coincidencia no codiciosa. Los cuantificadores codiciosos (.*?, .+? etc) son una extensión de Perl 5 que no es compatible con las expresiones regulares tradicionales.

Si su condición de parada es de un solo carácter, la solución es fácil; en vez de

a(.*?)b

puedes igualar

a[^ab]*b

es decir, especificar una clase de caracteres que excluya los delimitadores inicial y final.

En el caso más general, puede minuciosamente construye una expresión como

start(|[^e]|e(|[^n]|n(|[^d])))end

para capturar una coincidencia entre start y la primera aparición de end. Observe cómo la subexpresión con paréntesis anidados detalla una serie de alternativas que entre ellas permiten e solo si no es seguido por nd y así sucesivamente, y también tenga cuidado de cubrir la cadena vacía como una alternativa que no coincida con lo que no está permitido en ese punto en particular.

Por supuesto, el enfoque correcto en la mayoría de los casos es usar un analizador adecuado para el formato que está tratando de analizar, pero a veces, tal vez uno no esté disponible, o tal vez la herramienta especializada que está utilizando insiste en una expresión regular y nada demás.

Respondido 08 Jul 20, 19:07

import regex
text = 'ask her to call Mary back when she comes back'                           
p = r'(?i)(?s)call(.*?)back'
for match in regex.finditer(p, str(text)):
    print (match.group(1))

Salida: María

Respondido 09 Jul 20, 16:07

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.