Cómo hacer un partido no codicioso en grep?


Quiero grep la coincidencia más corta y el patrón debe ser algo así como:

<car ... model=BMW ...>
...
...
...
</car>

... significa cualquier carácter y la entrada es de varias líneas.

Author: kenorb, 2010-06-12

5 answers

Estás buscando un partido no codicioso (o perezoso). Para obtener una coincidencia no codiciosa en expresiones regulares, debe usar el modificador ? después del cuantificador. Por ejemplo, puede cambiar .* a .*?.

Por defecto grep no soporta modificadores no codiciosos, pero puedes usar grep -P para usar la sintaxis de Perl.

 202
Author: Mark Byers,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-02-04 13:02:15

Actualmente el .*? solo funciona en perl. No estoy seguro de cuál sería la sintaxis de regexp extendida grep equivalente. Afortunadamente puedes usar la sintaxis de perl con grep para que grep -P funcione pero grep -E que es lo mismo que egrep no funcione (sería codicioso).

Véase también: http://blog.vinceliu.com/2008/02/non-greedy-regular-expression-matching.html

 75
Author: John Smith,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-11-12 13:31:25

Mi grep que funciona después de probar cosas en este hilo:

echo "hi how are you " | grep -shoP ".*? "

Solo asegúrate de añadir un espacio a cada una de tus líneas

(La mía fue una búsqueda línea por línea para escupir palabras)

 8
Author: jonz,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-09-27 19:18:31

grep

Para una coincidencia no codiciosa en grep podría usar una clase de carácter negada. En otras palabras, trate de evitar comodines.

Por ejemplo, para obtener todos los enlaces a archivos jpeg del contenido de la página, usarías:

grep -o '"[^" ]\+.jpg"'

Para tratar con múltiples líneas, canalice la entrada a través de xargs primero. Para el rendimiento, el uso ripgrep.

 5
Author: kenorb,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-04-12 15:47:56

La respuesta corta está usando la siguiente expresión regular:

(?s)<car .*? model=BMW .*?>.*?</car>
  • (?s) - esto hace una coincidencia a través de multilínea
  • .*? - coincide con cualquier personaje, un número de veces de una manera perezosa (mínimo match)

Una respuesta (poco) más complicada es:

(?s)<([a-z\-_0-9]+?) .*? model=BMW .*?>.*?</\1>

Esto hará posible hacer coincidir car1 y car2 en el siguiente texto

<car1 ... model=BMW ...>
...
...
...
</car1>
<car2 ... model=BMW ...>
...
...
...
</car2>
  • (..) representa un grupo de captura
  • \1 en este contexto coincide con el mismo texto como coincidente más reciente por captura del grupo número 1
 0
Author: jmc,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-09-13 19:17:23