Tubería de varias líneas dentro del script bash

Tengo algunos loggings complicados que bash analizar. Lo que quiero es encontrar una cadena H , get la columna 5 de la línea que coincida, y luego tomar todas las otras líneas donde la columna 5 coincide con la línea con la cadena H.

Ejemplo de input

abcd 31 1 abcd 31 H abcd 31 2 abcd 32 1 abdd 32 2 abcd 33 1 abcd 33 H abcd 33 2 

Rendimiento esperado

 abcd 31 1 abcd 31 H abcd 31 2 abcd 33 1 abcd 33 H abcd 33 2 

Entonces, he podido hacerlo haciendo dos scripts separados: script1 | xargs -n1 | script2 script1 | xargs -n1 | script2

script1 busca la cadena H y luego imprime la quinta columna.
cat logfile | grep 'H' | awk '{print $5}'

script2 luego imprime todas las otras líneas del file de logging donde la columna 5 coincide con el resultado del primer script: cat logfile | awk -v var="$1" '$5 == var' cat logfile | awk -v var="$1" '$5 == var'

Quiero hacer que el file de input, el file de logging, una variable, de modo que pueda usar $ 1 en el script, y luego script logfile . Pero luego debo fusionar los dos scripts en un script, porque ambos scripts analizan el mismo file de logging. ¿Cuál es, en términos generales, el enfoque correcto para hacer esto? Digo en general, porque soy un recién llegado al bash scripting.

Los dos problemas que encuentro son, en primer lugar: el $ 1 del primer script (que es el file de logging) es diferente del $ 1 en el segundo script (el número que es el resultado del primer script) que canalizo a awk. En segundo lugar, no puedo encontrar el equivalente de xargs -n1 para usar dentro de un script bash.

El segundo awk lee dos inputs, una después de otra, desde la salida canalizada del primer awk y luego desde el file mismo. Una forma de identificar el inicio de la segunda input es que NR (el número del R ecord de input actual, en general) ya no coincide con FNR (el número de logging del file actual). Tenga en count que - como ARCHIVO, arg significa que awk recibe los datos de stdin (a través de un conducto , en este caso).

 awk '$6=="H"{print $5}' "$1" | awk 'NR==FNR{k[$1];next} $5 in k{print}' - "$1" 

Tenga en count que el método anterior para identificar la segunda input es de uso común, pero no se comporta como se espera / desea cuando no hay nada que leer desde la primera input. Para los requisitos de este trabajo, no importará si la primera imput no ofrece nada. La lógica nunca pasará NR=FNR donde buildá una list de valor de índice k (es decir, $1 desde el file principal) – pero nunca se hace nada con ellos – por lo que la secuencia de commands funciona con una input nula a través de la tubería, pero solo por un efecto secundario desorderado de la lógica particular utilizada.

Sin embargo, en GNU awk ( gawk ), hay una forma segura de identificar el file / tubería actual. Hay una variante especial para los arguments de FILE línea de command: "… un argumento que tiene la forma var = value, asigna valor a la variable var-it no especifica ningún file". – ver: Otros arguments de la línea de command La location de tales var = value args es significativa – los valores necesarios para un ARCHIVO específico deben colocarse en la línea de command antes de su ARCHIVO asociado – el var = valor posterior no se aplica dentro de awk hasta los files anteriores / la tubería ha sido completamente leída.

Aquí está la versión var = value .

 gawk '$6=="H"{print $5}' "$1" | gawk 'fn==1{k[$1];next} $5 in k{print}' fn=1 - fn=2 "$1" 

salida (es lo mismo para ambas versiones de script)

 abcd 31 1 abcd 31 H abcd 31 2 abcd 33 1 abcd 33 H abcd 33 2