我正在使用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
答案 0 :(得分:4)
假设该模式在文件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创建一个awk变量pat
,其中包含文件pattern
的内容。
如果您的shell是bash,则此命令的效率稍高一些为pat="$(<pattern)"
。 (除非您确定您的shell为bash,否则请不要使用它。)
$0 ~ pat
这告诉awk打印与模式匹配的任何记录。
$0
是当前记录的内容。 ~
告诉awk在$0
中的文本和pat
中的正则表达式之间进行匹配。
(如果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
答案 1 :(得分:2)
这是我微不足道的尝试:
awk -v RS="" -v FS="\n" -v op=001 -v ctrl=00 -v ini=0 '$2~op&&$3~ctrl&&$4~ini' data.txt
答案 2 :(得分:1)
到目前为止,最好的方法是John1024使用awk
的一种方法,因为您可以一次性完成,如果您确实想使用grep
解决方案,则可以使用:
$ grep -m 1 -zoP 'Packet\s*[^\s]*\s*(?=op_3b\s*:\s*001\s*ctrl_2b\s*:\s*00\sini_count\s*:\s*0)' file
Packet LP
注释:
-m 1
将使grep在第一个匹配项后返回,如果您的模式出现多次,则可以将其删除。-z
允许多行模式,因为它启用了ASCII NUL
字符而不是普通的EOL -o
仅将结果匹配显示为输出,而不是整个文件-P
激活perl正则表达式如果您要获得行号:
grep -n -f <(grep -m 1 -zoP 'Packet\s*[^\s]*\s*(?=op_3b\s*:\s*001\s*ctrl_2b\s*:\s*00\sini_count\s*:\s*0)' file) file
21:Packet LP
但是您需要进行2次传递,因此在15GB的文件上awk
是最好的方法。
答案 3 :(得分:0)
如果您的数据位于“ d”文件中,请尝试:
grep -nEA2 '^op_3b\s*:\s*001' d
编辑上面的001
号作为关键字搜索