我有一些复杂的日志需要解析。我想要的是找到一个字符串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 意味着告诉awk
从stdin
(通过管道, 在这种情况下)。
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