我有一个巨大的日志文件,想要 grep 第一次出现的模式,然后找到另一个模式就在之后这种情况的发生。
例如:
123
XXY
214
ABC
182
558
ABC
856
ABC
在我的例子中,我想找到182
然后找到下一个的发生ABC
第一次出现很简单:
grep -n -m1 "182" /var/log/file
这输出:
5:182
如何找到下一个出现的 ABC?
我的想法是根据行号 182告诉grep
跳过第一n
行(在上面的示例中)。但是我该怎么做呢?n=5
答案1
您可以在一次完成中sed
使用范围和uit 输入:q
sed '/^182$/p;//,/^ABC$/!d;/^ABC$/!d;q'
类似地,在 GNU 中,grep
您可以将输入拆分为两个grep
:
{ grep -nxF -m1 182; grep -nxF -m1 ABC; } <<\IN
123
XXY
214
ABC
182
558
ABC
856
ABC
IN
...打印...
5:182
2:ABC
...表示第一个grep
找到了-F
固定字符串文字,-x
整行182从读取开始匹配 5 行,第二个找到类似类型的ABC从读取的开头匹配 2 行 - 或 2 行后首先grep
辞职阅读第 5 行。
从man grep
:
-m NUM, --max-count=NUM
Stop reading a file after NUM matching
lines. If the input is standard input from
a regular file, and NUM matching lines are
output, grep ensures that the standard input
is positioned to just after the last
matching line before exiting, regardless of
the presence of trailing context lines.
This enables a calling process to resume a
search.
为了可重现的演示,我使用了此处文档,但您可能应该这样做:
{ grep ...; grep ...; } </path/to/log.file
它还可以与其他 shell 复合命令结构一起使用,例如:
for p in 182 ABC; do grep -nxFm1 "$p"; done </path/to/log.file
答案2
grep
与 Perl 兼容的正则表达式 ( ) 一起使用pcregrep
:
pcregrep -Mo '182(.|\n)*?\KABC'
选项-M
允许模式匹配多行,并且\K
不将匹配的模式(到目前为止)包含到输出中。\K
如果您想获得整个区域,则可以将其删除。
答案3
> awk '/^182$/ { startline=1; }; startline == 0 { next; }; /^ABC$/ { print "line " NR ": " $0; exit; }' file
line 7: ABC
答案4
另一种变体是这样的:
grep -n -A99999 "182" /var/log/file|grep -n -m1 "ABC"
标志 -An 在比赛后 grep n 行和 99999 只是为了确保我们不会错过任何东西。较大的文件应该有更多的行(使用“wc -l”检查)。