Respuestas:
Estás buscando una pareja no codiciosa (o perezosa). Para obtener una coincidencia no codiciosa en expresiones regulares, debe usar el modificador ?
después del cuantificador. Por ejemplo, puede cambiar .*
a .*?
.
De forma predeterminada grep
, no admite modificadores no codiciosos, pero puede grep -P
usar la sintaxis de Perl.
.
coincidir con las nuevas líneas se llama DOTALL o modo de una sola línea ; Ruby es el único que lo llama multilínea . En los otros sabores, multilínea es el modo que permite que los anclajes ( ^
y $
) coincidan en los límites de la línea. Ruby no tiene modo equivalente porque en Ruby siempre funcionan de esa manera.
-P
era completamente nuevo para mí, he estado felizmente trabajando durante años, y solo usando -E
... ¡tantos años desperdiciados! - Nota personal: vuelva a leer las páginas Man como algo normal (¡incluso más!), Nunca digiere suficientes interruptores y opciones.
grep
no es compatible -P
, pero si lo usa egrep
, puede usar el .*?
patrón para lograr el mismo resultado. egrep -o 'start.*?end' text.html
-P
pero -E
llamaría, egrep
por lo tanto, los .*?
trabajos sugeridos funcionan bien.
En realidad el .*?
único funciona en perl
. No estoy seguro de cuál sería la sintaxis de expresión regular grep extendida equivalente. Afortunadamente, puede usar la sintaxis de perl con grep, por grep -P
lo que funcionaría, pero grep -E
es lo mismo egrep
que no funcionaría (sería codicioso).
Ver también: http://blog.vinceliu.com/2008/02/non-greedy-regular-expression-matching.html
grep -P
no funciona en GNU grep 2.9 - solo lo probé (no es un error, solo silenciosamente no aplica ?
. Intertestly tampoco la clase no, por ejemplo:env|grep '[^\=]*\='
grep -P
opción o pgrep
comando en Darwin / OS X 10.8 Mountain Lion, pero egrep
funciona muy bien.
pgrep
comando en mi cuadro OS X 10.9, pero es un programa completamente diferente cuyo propósito es "encontrar o señalar procesos por nombre".
Mi grep que funciona después de probar cosas en este hilo:
echo "hi how are you " | grep -shoP ".*? "
Solo asegúrate de agregar un espacio a cada una de tus líneas
(El mío fue una búsqueda línea por línea para escupir palabras)
-shoP
nice mnemonic :)
echo "bbbbb" | grep -shoP 'b.*?b'
Es un poco una experiencia de aprendizaje. Lo único que me funcionó en términos de pereza explícita también.
grep
Para una coincidencia no codiciosa grep
, puede usar una clase de caracteres negada. En otras palabras, trate de evitar los comodines.
Por ejemplo, para obtener todos los enlaces a archivos jpeg del contenido de la página, usaría:
grep -o '"[^" ]\+.jpg"'
Para tratar con varias líneas, canalice la entrada xargs
primero. Para rendimiento, uso ripgrep
.
La respuesta corta es usar la siguiente expresión regular:
(?s)<car .*? model=BMW .*?>.*?</car>
Una respuesta (poco) más complicada es:
(?s)<([a-z\-_0-9]+?) .*? model=BMW .*?>.*?</\1>
Esto hará posible que coincidan car1 y car2 en el siguiente texto
<car1 ... model=BMW ...>
...
...
...
</car1>
<car2 ... model=BMW ...>
...
...
...
</car2>
Lo siento, llego 9 años tarde, pero esto podría funcionar para los espectadores en 2020.
Supongamos que tienes una línea como "Hello my name is Jello"
. Ahora desea encontrar las palabras que comienzan 'H'
y terminan 'o'
con cualquier número de caracteres intermedios. Y no queremos líneas, solo queremos palabras. Entonces para eso podemos usar la expresión:
grep "H[^ ]*o" file
Esto devolverá todas las palabras. La forma en que esto funciona es que: permitirá todos los caracteres en lugar del espacio en el medio, de esta manera podemos evitar varias palabras en la misma línea.
Ahora puede reemplazar el carácter de espacio con cualquier otro carácter que desee. Suponga que la línea inicial era "Hello-my-name-is-Jello"
, entonces puede obtener palabras usando la expresión:
grep "H[^-]*o" file
Sé que es una publicación un poco muerta, pero acabo de notar que esto funciona. Eliminó tanto la limpieza como la limpieza de mi salida.
> grep -v -e 'clean\-\?up'
> grep --version grep (GNU grep) 2.20