Pregunta Combina múltiples comandos de Unix en una salida


Necesito buscar en nuestros registros de correo para obtener una dirección de correo electrónico específica. Mantenemos un archivo actual llamado registro electrónico así como el valor de una semana de archivos .bz2 en la misma carpeta. Actualmente, estoy ejecutando los siguientes comandos para buscar el archivo:

grep person@domain.com maillog
bzgrep person@domain.com *.bz2

¿Hay alguna manera de combinar el grep y bzgrep comandos en una sola salida? De esa manera, podría canalizar los resultados combinados a un solo correo electrónico o un solo archivo.


9
2018-03-08 22:03


origen




Respuestas:


Otra forma es

{ grep ...; bzgrep ...;} >file

&& tiene la dificultad que la bzgrep no se ejecutaría si el grep ha fallado.

Tenga en cuenta el espacio obligatorio después de la apertura de la llave y el punto y coma después del último comando. Alternativamente, puedes usar la sintaxis de subshell (paréntesis en lugar de llaves), que no es tan delicada:

(grep ...; bzgrep ...) >file

24
2018-03-08 22:25



+1 para el mejor enfoque de shell de propósito general para este problema. La agrupación de shell es una característica generalmente infrautilizada. - Phil Hollenback
Esto es exactamente lo que estaba buscando. ¡Gracias! - Ben McCormack
No quieres decir () en lugar de {}? - Ehtesh Choudhury
En arch linux esto funcionó con () pero no {}De cualquier manera, +1 ya que esto es lo que necesitaba! - Chris Magnuson


bzgrep automáticamente configura el valor predeterminado de grep si un archivo no está comprimido en bzip. Por lo tanto, lo siguiente debería ser suficiente:

bzgrep person@domain.com maillog *bz2 | mail -s "logs yay" someuser@blah

oh también, por supuesto, aquí está mi obligatorio GNU paralelo solución también:

parallel -m bzgrep person@domain.com ::: maillog* *bz2 | mail -s "logs yay" someuser@blah

lo que podría ser mucho más rápido si está revisando muchos archivos.


11
2018-03-08 23:01





Aquí hay otra forma de hacerlo (asumiendo que estás ejecutando bash, que probablemente lo estés haciendo):

cat <(bzgrep ...) <(grep ...)

Aquí bash alimenta de forma transparente la salida de los comandos bzgrep y grep en cat como si fueran archivos (y están más o menos bajo el capó, los detalles se encuentran en la url en la parte inferior).

En su caso particular, recomendaría la solución de Phil, pero lo anterior es un buen truco para mantener en su bolsa.

Si estás interesado, puedes leer más aquí: http://www.tldp.org/LDP/abs/html/process-sub.html


2
2018-03-09 01:11



Ah, sí, la respuesta canónica para '¿Cómo difieres la salida de dos procesos'? Un buen truco para saber. - Phil Hollenback


En el momento de escribir esto, la sintaxis de la respuesta aceptada era incorrecta para la mayoría, si no todas, las conchas derivadas de Bourne, incluidas bash. Sugerí una edición a la parte superior y acepté una respuesta para solucionarlo, pero también estaba dispuesto a agregar toda esta otra información, y esto habría sido más una reescritura en lugar de una edición.

Puedes usar comandos compuestos:

{ grep ...; bzgrep ...; } >file

..o subshells (note los paréntesis en lugar de llaves):

(grep ...; bzgrep ...) >file

..para agrupar los comandos. La forma subshell tiene una sintaxis más agradable (más indiferente a la falta de espacios en blanco y le permite omitir el último punto y coma), pero o bien forza un nuevo proceso, o "finge" haciendo que los comandos se ejecuten en un entorno limpio. Ambos tienen ventajas en función de lo que quieras hacer, lo que no importa aquí, pero vale la pena buscarlos si quieres más habilidad con el shell.

Nota: También puedes usar la canalización con estos trucos, por lo que podrías hacer algo como esto:

{ grep ...; bzgrep ...; } | less

PD Si no le importa el orden de las coincidencias en su salida combinada, puede usar una sola & entre los dos comandos, así: { grep ... & bzgrep ...; }. Entonces los dos comandos se ejecutan simultáneamente: grep se inicia y el shell lo coloca en segundo plano, luego el shell ejecutará el bzgrep. (Pero hay una pequeña advertencia al respecto, ya que la explicación sobre la redirección de archivos y el almacenamiento en búfer del flujo de archivos puede causar que una pequeña parte de las líneas en el archivo de salida se dividan / modifiquen: si vería esto dependerá de cómo grep, bzgrepy libc  stdio.h Se implementan funciones. En la mayoría de las implementaciones, creo que canalizar el comando antes de redirigir a un archivo evitará el problema, por lo que podría hacerlo { foo & bar; } | cat - >file como una solución.)


1
2018-03-14 05:39





Puede vincular los comandos junto con &&, lo que le permitirá ejecutar cada comando.

también puede agregar >> textfile.txt al final de cada comando y hacer que la salida golpee un archivo y luego envíe ese archivo.


0
2018-03-08 22:08



Como mencionó el geekosaurio, && no debe usarse aquí porque el valor de retorno de grep depende de si encontró algo o no. Si lo hiciste grep ... && bzgrep ..., si grep no tuvo aciertos, devolvería el error y el comando se detendría. >> aunque es una buena idea, a diferencia de >, agregará salida al final de un archivo existente. - DerfK
derecho me había olvidado de la condición de salida que impide el segundo comando. - Mike