首页 > 解决方案 > 使用 grep 或其他命令返回多行模式的行号

问题描述

我正在使用该less命令浏览一个非常大的文本日志文件(15 GB),并试图搜索多行模式,但经过一番调查,less命令只能搜索单行模式。

有没有办法使用grep或其他命令来返回多行模式的数字行?

日志的格式在数十万次迭代中是这样的:

Packet A
op_3b       : 001
ctrl_2b     : 01
ini_count   : 5

Packet F
op_3b       : 101
ctrl_2b     : 00
ini_count   : 4

Packet X
op_3b       : 010
ctrl_2b     : 11
ini_count   : 98

Packet CA
op_3b       : 100
ctrl_2b     : 01
ini_count   : 5

Packet LP
op_3b       : 001
ctrl_2b     : 00
ini_count   : 0

Packet ZZ
op_3b       : 111
ctrl_2b     : 01
ini_count   : 545

Packet QEA
op_3b       : 111
ctrl_2b     : 11
ini_count   : 0

我想要得到的是有grep或其他一些命令来返回这三行模式发生时的行号的开始:

op_3b       : 001
ctrl_2b     : 00
ini_count   : 0

标签: linuxawksedgrepless-unix

解决方案


假设该模式在pattern这样的文件中:

$ cat pattern
op_3b       : 001
ctrl_2b     : 00
ini_count   : 0

然后,尝试:

$ awk '$0 ~ pat' RS=  pat="$(cat pattern)" logfile
Packet LP
op_3b       : 001
ctrl_2b     : 00
ini_count   : 0

这个怎么运作

  • RS=

    这会将记录分隔符RS设置为空字符串。这告诉 awk 使用空行作为记录分隔符。

  • pat="$(cat pattern)"

    这告诉 awk 创建一个pat包含文件内容的awk 变量pattern

    如果你的 shell 是 bash,那么这个命令的稍微更有效的形式是pat="$(<pattern)". (除非你确定你的 shell 是 bash,否则不要使用它。)

  • $0 ~ pat

    这告诉 awk 打印与模式匹配的任何记录。

    $0是当前记录的内容。 告诉 awk 在 in 的文本和 in 的正则表达式~之间进行匹配。$0pat

    (如果 的内容pattern有任何正则表达式活动字符,我们需要转义它们。您当前的示例没有任何内容,所以这不是问题。)

另类风格

有些人喜欢用不同的风格来定义 awk 变量:

$ awk -v RS=  -v pat="$(cat pattern)" '$0 ~ pat' logfile
Packet LP
op_3b       : 001
ctrl_2b     : 00
ini_count   : 0

这同样有效。

显示行号

$ awk -F'\n' '$0 ~ pat{print "Line Number="n+1; print "Packet" $0} {n=n+NF-1}' RS='Packet'  pat="$(cat pattern)" logfile
Line Number=20
Packet LP
op_3b       : 001
ctrl_2b     : 00
ini_count   : 0

推荐阅读