Quiero encontrar todas las líneas en varios archivos que coincidan con uno de los dos patrones. Traté de encontrar los patrones que estoy buscando escribiendo
grep (foo|bar) *.txt
pero el shell lo interpreta |
como una tubería y se queja cuando bar
no es un ejecutable.
¿Cómo puedo buscar múltiples patrones en el mismo conjunto de archivos?
Respuestas:
Primero, debe proteger el patrón de la expansión del shell. La forma más fácil de hacerlo es poner comillas simples alrededor. Las comillas simples evitan la expansión de cualquier cosa entre ellas (incluidas las barras invertidas); lo único que no puedes hacer es tener comillas simples en el patrón.
Si necesita una comilla simple, puede escribirla como
'\''
(literal de cadena final, comilla literal, literal de cadena abierta).En segundo lugar, grep admite dos sintaxis para patrones. La antigua sintaxis predeterminada ( expresiones regulares básicas ) no admite el
|
operador alternation ( ), aunque algunas versiones lo tienen como extensión, pero escrito con una barra diagonal inversa.La forma portátil es usar la sintaxis más nueva, expresiones regulares extendidas . Debe pasar la
-E
opción agrep
para seleccionarlo. En Linux, también puede escribir enegrep
lugar degrep -E
(en otros unices, puede hacer que sea un alias).Otra posibilidad cuando solo está buscando cualquiera de varios patrones (en lugar de crear un patrón complejo usando la disyunción) es pasar múltiples patrones a
grep
. Puede hacer esto precediendo cada patrón con la-e
opción.fuente
fgrep
ogrep -F
, para patrones pequeños, la diferencia será insignificante, pero a medida que se alargan, los beneficios comienzan a mostrarse ...grep -F
tiene un beneficio de rendimiento real depende de la implementación de grep: algunos de ellos aplican el mismo algoritmo de todos modos, por lo que eso-F
hace la diferencia solo en el tiempo dedicado a analizar el patrón y no en el tiempo de búsqueda. GNU grep no es más rápido con-F
, por ejemplo (también tiene un error que hacegrep -F
más lento en configuraciones locales multibyte, ¡el mismo patrón constante congrep
es en realidad significativamente más rápido!). Por otro lado, BusyBox grep se beneficia mucho de-F
los archivos grandes.egrep
es anteriorgrep -E
. No es específico de GNU (ciertamente no tiene nada que ver con Linux). En realidad, todavía encontrará sistemas como Solaris donde el valor predeterminadogrep
todavía no es compatible-E
.o
citando selectivamente la página de manual de gnu-grep:
(...)
Al principio no leí más, así que no reconocí las sutiles diferencias:
Siempre usé egrep y parens innecesariamente, porque aprendí de los ejemplos. Ahora aprendí algo nuevo. :)
fuente
Como dijo TC1,
-F
parece ser una opción utilizable:fuente
En primer lugar, debe usar comillas para caracteres especiales. Segundo, aun así,
grep
no entenderá la alternancia directamente; necesitaría usaregrep
, o (grep
solo con GNU )grep -E
.(Los paréntesis son innecesarios a menos que la alternancia sea parte de una expresión regular más grande).
fuente
grep -E
es más estándar queegrep
.Si no necesita expresiones regulares, es mucho más rápido de usar
fgrep
ogrep -F
con múltiples parámetros -e, como este:fgrep
(alternativamentegrep -F
) es mucho más rápido que grep normal porque busca cadenas fijas en lugar de expresiones regulares.fuente
fgrep
está en desuso.Puede probar el siguiente comando para obtener el resultado:
fuente
Una forma barata y alegre de buscar múltiples patrones:
fuente
-f
opción de grep toma un archivo con múltiples patrones. En lugar de crear un archivo temporal (que puede olvidar eliminar después), simplemente use la sustitución del proceso del shell:grep -f <(echo foo; echo bar) *.txt
Pipe (
|
) es un carácter de shell especial, por lo que debe ser escapado (\|
) o citado según el manual (man bash
):Ver: ¿Qué personajes se deben escapar en Bash?
Aquí hay algunos ejemplos (usando herramientas no mencionadas aún):
Utilizando
ripgrep
:rg "foo|bar" *.txt
rg -e foo -e bar *.txt
Utilizando
git grep
:git grep --no-index -e foo --or -e bar
Nota: También admite expresiones booleanas como
--and
,--or
y--not
.Para la operación AND por línea, vea: ¿Cómo ejecutar grep con múltiples patrones AND?
Para la operación AND por archivo, consulte: ¿Cómo verificar que existan todas las cadenas múltiples o expresiones regulares en un archivo?
fuente
Tuve acceso a registros donde las fechas se formatearon estúpidamente: [30 / Jun / 2013: 08: 00: 45 +0200]
Pero necesitaba mostrarlo como: 30 / Jun / 2013 08:00:45
El problema es que al usar "OR" en mi declaración grep, recibí las dos expresiones de coincidencia en dos líneas separadas.
Aquí está la solución:
fuente
TL; DR: si desea hacer más cosas después de hacer coincidir uno de los múltiples patrones, enciérrelos como en
\(pattern1\|pattern2\)
ejemplo: Quiero encontrar todos los lugares donde una variable que contiene el nombre 'fecha' se define como una Cadena o int. (por ejemplo, "int cronDate =" o "String textFormattedDateStamp ="):
Con
grep -E
, no necesita escapar de los paréntesis o la tubería, es decir,grep -E '(int|String) [a-zA-Z_]*date[a-zA-Z_]* ='
fuente
Esto funciona para mi
fuente
Hay varias formas de hacer esto.
grep 'foo\|bar' *.txt
egrep 'foo|bar' *.txt
find . -maxdepth 1 -type f -name "*.txt" | xargs grep 'foo\|bar'
find . -maxdepth 1 -type f -name "*.txt" | xargs egrep 'foo|bar'
Las opciones 3ra y 4ta solo aparecerán en los archivos y evitarán que los directorios tengan
.txt
sus nombres.Entonces, según su caso de uso, puede usar cualquiera de las opciones mencionadas anteriormente.
¡¡Gracias!!
fuente
para añadir a la respuesta de @ geekosaur , si tiene múltiples patrones que también contienen pestañas y espacio, use el siguiente comando
donde
[[:blank:]]
está la clase de caracteres RE que representa un espacio o un carácter de tabulaciónfuente