regulares - grep para 2 palabras existentes en la misma línea
grep buscar palabra exacta (8)
¿cómo grep para las líneas que contienen dos palabras de entrada en la línea? Estoy buscando líneas que contengan ambas palabras, ¿cómo hago eso? Probé con una pipa como esta:
grep -c "word1" |grep -r "word2" logs
simplemente sobresale después del primer comando de tubería. ¿por qué?
Prescripción
Una simple reescritura del comando en la pregunta es:
grep "word1" logs | grep "word2"
El primer grep
encuentra líneas con ''word1'' del archivo ''logs'' y luego las introduce en el segundo grep
que busca las líneas que contienen ''word2''.
Sin embargo, no es necesario usar dos comandos como ese. Puede usar grep
extendido ( grep -E
o egrep
):
grep -E ''word1.*word2|word2.*word1'' logs
Si sabes que ''word1'' precederá a ''word2'' en la línea, ni siquiera necesitas las alternativas y grep
regular:
grep ''word1.*word2'' logs
Las variantes de ''un comando'' tienen la ventaja de que solo hay un proceso en ejecución, por lo que las líneas que contienen ''palabra1'' no tienen que pasarse por un conducto al segundo proceso. Cuánto importa esto depende de cuán grande es el archivo de datos y cuántas líneas coinciden con ''word1''. Si el archivo es pequeño, no es probable que el rendimiento sea un problema y ejecutar dos comandos está bien. Si el archivo es grande pero solo unas pocas líneas contienen ''word1'', no se pasarán muchos datos en la tubería y usar dos comandos está bien. Sin embargo, si el archivo es enorme y ''word1'' ocurre con frecuencia, entonces puede estar pasando datos significativos por el conducto donde un único comando evita esa sobrecarga. Contra eso, la expresión regular es más compleja; es posible que necesite compararla para descubrir qué es lo mejor, pero solo si el rendimiento realmente importa. Si ejecuta dos comandos, debe apuntar a seleccionar la palabra menos frecuente en el primer grep
para minimizar la cantidad de datos procesados por el segundo.
Diagnóstico
El script inicial es:
grep -c "word1" | grep -r "word2" logs
Esta es una secuencia de comando impar. El primer grep
contará el número de apariciones de ''word1'' en su entrada estándar, e imprimirá ese número en su salida estándar. Hasta que indique EOF (por ejemplo, escribiendo Control-D ), se quedará allí, esperando que escriba algo. El segundo grep
realiza una búsqueda recursiva de ''word2'' en los archivos debajo de los logs
directorio (o, si es un archivo, en los logs
archivos). O, en mi caso, fallará ya que no hay un archivo ni un directorio llamado logs
donde estoy ejecutando la canalización. Tenga en cuenta que el segundo grep
no lee su entrada estándar en absoluto, por lo que el tubo es superfluo.
Con Bash, el shell padre espera hasta que todos los procesos en la tubería hayan salido, por lo que se queda esperando que grep -c
termine, lo que no sucederá hasta que indique EOF. Por lo tanto, su código parece bloquearse. Con Heirloom Shell , el segundo grep
completa y sale, y el shell solicita nuevamente. Ahora tiene dos procesos en ejecución, el primer grep
y el shell, y ambos están tratando de leer desde el teclado, y no está determinado cuál recibe una determinada línea de entrada (o cualquier indicación EOF dada).
Tenga en cuenta que incluso si escribió datos como entrada en el primer grep
, solo obtendría líneas que contengan ''word2'' en la salida.
Nota:
En un momento, la respuesta utilizada:
grep -E ''word1.*word2|word2.*word1'' "$@"
grep ''word1.*word2'' "$@"
Esto activó los comentarios a continuación.
El problema principal es que no ha suministrado el primer grep con ninguna entrada. Necesitarás reordenar tu comando algo así como
grep "word1" logs | grep "word2"
Si desea contar las ocurrencias, coloque una ''-c'' en el segundo grep.
Para grep dos palabras al mismo tiempo, use este comando de shell:
eval "</dev/stdin $(printf "|grep ''%s''" word1 word2)" FILE
Si usa esto con más frecuencia, esto se puede definir como un alias:
alias grep-all="</dev/stdin $(printf "|grep ''%s''" word1 word2)"
Luego ejecuta solo
grep-all FILE
Si tiene varios patrones almacenados en el archivo, consulte: Igualar todos los patrones del archivo a la vez .
También verifique: ¿Cómo ejecutar grep con múltiples patrones AND?
Use grep:
grep -wE "string1|String2|...." file_name
O puede usar:
echo string | grep -wE "string1|String2|...."
Usted gato intenta con el comando debajo
cat log|grep -e word1 -e word2
podrías usar awk. Me gusta esto...
cat <yourFile> | awk ''/word1/ && /word2/''
El orden no es importante. Entonces, si tienes un archivo y ...
un archivo llamado, file1 contiene:
word1 is in this file as well as word2
word2 is in this file as well as word1
word4 is in this file as well as word1
word5 is in this file as well as word2
entonces,
/tmp$ cat file1| awk ''/word1/ && /word2/''
resultará en,
word1 is in this file as well as word2
word2 is in this file as well as word1
sí, awk es más lento.
¿Por qué pasas -c
? Eso solo mostrará el número de coincidencias. Del mismo modo, no hay ninguna razón para usar -r
. Te sugiero que leas man grep
.
Para grep para 2 palabras existentes en la misma línea, simplemente hazlo:
grep "word1" FILE | grep "word2"
grep "word1" FILE
imprimirá todas las líneas que tengan word1 en ellas desde FILE, y luego grep "word2"
imprimirá las líneas que tienen word2 en ellas. Por lo tanto, si combina estos utilizando una tubería, mostrará líneas que contienen tanto word1 como word2.
Si solo quieres contar cuántas líneas tenían las 2 palabras en la misma línea, hazlo:
grep "word1" FILE | grep -c "word2"
Además, para responder a su pregunta, ¿por qué se bloquea? En grep -c "word1"
, no especificó ningún archivo. Por lo tanto, grep
espera la entrada desde stdin
, que es por lo que parece colgarse. Puede presionar Ctrl + D para enviar un EOF (fin de archivo) para que se cierre.
grep word1 file_name | grep word2
esa parece la forma más fácil para mí