在 bash 脚本中通过管道传输多行

在 bash 脚本中通过管道传输多行

我有一些复杂的日志需要解析。我想要的是找到一个字符串H,从匹配的行中获取第 5 列,然后获取第 5 列与字符串匹配的所有其他行H

输入示例

a b c d 31 1
a b c d 31 H
a b c d 31 2
a b c d 32 1
a b d d 32 2
a b c d 33 1
a b c d 33 H
a b c d 33 2

预期产出

a b c d 31 1
a b c d 31 H
a b c d 31 2
a b c d 33 1
a b c d 33 H
a b c d 33 2

因此,我可以通过制作两个单独的脚本来做到这一点: script1 | xargs -n1 | script2

脚本1搜索字符串H,然后打印第五列。
cat logfile | grep 'H' | awk '{print $5}'

脚本2然后打印日志文件中的所有其他行,其中第 5 列与第一个脚本的输出匹配: cat logfile | awk -v var="$1" '$5 == var'

我想使输入文件、日志文件成为一个变量,以便我可以在脚本中使用 $1,然后调用script logfile.但随后我必须将这两个脚本合并为一个脚本,因为这两个脚本解析相同的日志文件。一般来说,执行此操作的正确方法是什么?我说一般,因为我是 bash 脚本的新手。

我遇到的两个问题是,首先:第一个脚本(即日志文件)的 $1 与我通过管道传输到 awk 的第二个脚本(即第一个脚本的输出数字)中的 $1 不同。其次,我找不到xargs -n1在一个 bash 脚本中使用的等效项。

答案1

第二个awk读取两个输入,一个接一个 - 从第一个的管道输出awk,然后从文件本身。识别第二个输入开始的一种方法是NR当前输入的数量总体记录)不再匹配FNR(当前File 的记录号)。请注意,-作为 FILE arg 意味着告诉awkstdin(通过管道, 在这种情况下)。

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

请注意,上述识别第二输入的方法是常用的,但当没有从第一输入读取任何内容时,该方法无法按预期/期望的方式运行。对于这项工作的要求,如果第一个输入没有提供任何内容,那也没关系。该逻辑永远不会超过NR=FNR它将构建k索引值列表(即$1来自主文件)的地方 - 但不会对它们进行任何操作 - 因此该脚本通过管道使用空输入,但这只是因为所使用的特定逻辑的混乱副作用。

然而,在 GNU awk ( ) 中,有gawk一种确定当前文件/管道的可靠方法。命令行参数有一个特殊的变体FILE“...形式为 var=value 的参数将值赋给变量 var — 它根本不指定文件。”- 看:其他命令行参数 此类的放置变量=值args 很重要 - 特定文件所需的值必须放在命令行上其关联的文件 – 后续变量=值awk在前面的文件/管道被完全读取之前不会应用。

这里是变量=值版本。

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

输出(两个脚本版本相同)

a b c d 31 1
a b c d 31 H
a b c d 31 2
a b c d 33 1
a b c d 33 H
a b c d 33 2

相关内容