如何在匹配后仅显示下一行?

Posted

技术标签:

【中文标题】如何在匹配后仅显示下一行?【英文标题】:How to show only next line after the matched one? 【发布时间】:2011-11-19 01:37:45 【问题描述】:
grep -A1 'blah' logfile

多亏了这个命令,每行都包含“blah”,我得到了包含“blah”的行的输出以及日志文件中的下一行。这可能是一个简单的方法,但我找不到一种方法来省略具有“blah”的行并且only在输出中显示下一行。

【问题讨论】:

我想很多人会来这里寻找-A1选项 然后我用它来获取我的公共 IP。 :) curl whatismyip.org | grep -A1 'Your IP Address' 类似地 -B1, -B2, -B3, -A1, -A2, -A3 。 . . @shrek curl icanhazip.com(不需要 grep):) 您的问题回答了我的问题...-A1。谢谢! 【参考方案1】:

你可以试试 awk:

awk '/blah/getline; print' logfile

【讨论】:

对于任何真正想要 grep -A2 等效项(这是我需要的)的人,getline 只是吃掉这条线并继续下一条。所以对我有用的只是awk '/blah/getline; getline; print' logfile 我喜欢这个 getline 解决方案。 警告:假设您没有得到两个相邻的匹配行【参考方案2】:

我不知道用 grep 有什么方法可以做到这一点,但是可以使用 awk 来实现相同的结果:

awk '/blah/ getline;print' < logfile

【讨论】:

@jww 没有区别。从相隔几分钟的时间戳可以看出,我似乎在同一时间回答了。【参考方案3】:

如果你想坚持使用 grep:

grep -A1 'blah' logfile | grep -v "blah"

或者使用 sed:

sed -n '/blah/n;p;' logfile

【讨论】:

@Kent,感谢您的提示。不过,从我的 POV 来看,与 sed 或标记为最佳答案的 awk 答案相比,grep 更具可读性和易于掌握......但也许只是我个人 :) 对于那些好奇 -v 做什么的人: -v --invert-match 反转匹配的意义,选择不匹配的行。 (-v 由 POSIX 指定。) 我真的很喜欢这个答案,但是如果你连续有两行包含“blah”并且想要获得第二行(因为它是“匹配的下一行”)。我想不出任何用例,但值得注意。 最佳解决方案只是“ok”。如果第二行恰好也有“blah”,那你手上就会一团糟。 警告:假设您没有得到两个相邻的匹配行。然后“grep”会有额外的“--”行,而“sed”会跳过行。但我发现这种“sed”解决方案在不是这种情况下最有用。【参考方案4】:

您似乎在这里使用了错误的工具。 Grep 并没有那么复杂,我认为您想加强 awk 作为这项工作的工具:

awk '/blah/ getline; print $0 ' logfile

如果您遇到任何问题,请告诉我,我认为它非常值得学习一点 awk,它是一个很棒的工具 :)

附言这个例子没有赢得“无用的猫奖”;) http://porkmail.org/era/unix/award.html

【讨论】:

顺便说一句,您可以跳过打印中的“$0”。【参考方案5】:

如果下一行从不包含“blah”,您可以使用以下命令对其进行过滤:

grep -A1 blah logfile | grep -v blah

不需要使用cat logfile | ...

【讨论】:

如果你不喜欢 "cat" 但希望文件名位于复杂管道的开头,试试这个 &lt;logfile grep -A1 blah | grep -v blah 这是完全有效的 BASH!【参考方案6】:

管道是你的朋友......

使用grep -A1 显示匹配后的下一行,然后将结果通过管道传输到tail 并且只抓取1 行,

cat logs/info.log | grep "term" -A1 | tail -n 1

【讨论】:

如果“term”在最后一行,这将返回包含“term”的行,而不是什么都没有,这是你想要的。 tail -n 1 只会产生整个文件的最后一行【参考方案7】:

来自 raim 的出色回答,对我非常有用。将其扩展到打印是微不足道的,例如模式后的第 7 行

awk -v lines=7 '/blah/ for(i=lines;i;--i)getline; print $0 ' logfile

【讨论】:

【参考方案8】:

总的来说,我同意您在这里询问了很多 grep,而另一种工具可能是更好的解决方案。但是在嵌入式环境中,我可能不想让sedawk 只是为了做到这一点。我发现以下解决方案有效(只要它们不是连续匹配):

grep -A1 AT\+CSQ wvdial.out | grep -v AT\+CSQ

基本上,匹配它们,为每个匹配附加 1 行上下文,然后通过原始模式的反向匹配将其删除。这当然意味着您可以假设您的模式不会出现在“下一个”行中。

【讨论】:

警告:它还会在多个匹配项上输出“--”分隔符。【参考方案9】:

到目前为止,这个问题已经给出了很多很好的答案,但我仍然想念一个awk 没有使用getline 的答案。因为in general,没必要用getline,我会选择:

awk ' f && NR==f+1; /blah/ f=NR' file  #all matches after "blah"

awk '/blah/ f=NR f && NR==f+1' file   #matches after "blah" not being also "blah"

逻辑始终在于存储找到“blah”的行,然后打印后面一行的行。

测试

示例文件:

$ cat a
0
blah1
1
2
3
blah2
4
5
6
blah3
blah4
7

获取“blah”之后的所有行。如果它出现在第一个之后,则会打印另一个“blah”。

$ awk 'f&&NR==f+1; /blah/ f=NR' a
1
4
blah4
7

如果它们本身不包含“blah”,则获取“blah”之后的所有行。

$ awk '/blah/ f=NR f && NR==f+1' a
1
4
7

【讨论】:

这是一个很好的解决方案,可以通过两种可能的方式处理连续匹配的行...赞成完整性!【参考方案10】:

perl 单行警告

只是为了好玩...匹配后只打印一行

perl -lne '$. == $next && print; $next = ($.+1) if /match/' data.txt

更有趣...在匹配后打印接下来的十行

perl -lne 'push @nexts, (($.+1)..($.+10)) if /match/; $. ~~ @nexts && print' data.txt

有点作弊,因为实际上有两个命令

【讨论】:

你能解释一下$.==$next吗?显然,这不仅仅是当前行号与 $next 的数字比较,但我不明白它是如何/为什么工作的。 仅此而已。 $. == $next &amp;&amp; printprint if $. == $next 相同 啊,我明白了。谢谢!在 2 个部分中,每个部分都是正确的,并且在循环的单独、相邻的迭代中执行。我想如果关键是在任何匹配之后打印任何你想要颠倒顺序的行(表现得更像grep -A1)。如果您只想打印下一行而不是匹配的行,那么您将保持此顺序。 (只是注意 $next 将如何在连续比赛中被破坏)【参考方案11】:

grep /模式/ |尾-n 2 |头 -n 1

前 2 尾,然后前尾后尾,以在匹配后准确地获得第一行。

【讨论】:

【参考方案12】:

你可以使用 grep,然后在跳转中取行:grep -A1 'blah' logfile | awk 'NR%3==2' 也可以在匹配后取n行,例如:seq 100 | grep -A3 .2 | awk 'NR%5==4' 15 25 35 45 55 65 75 85 95 解释 - 在这里,我们要 grep 所有 *2 行并在其后取 3 行,即 *5。seq 100 | grep -A3 .2 会给你: 12 13 14 15 -- 22 23 24 25 -- ... 模数 (NR%5) 中的数字是 grep 添加的行(这里是标志 -A3 的 3 行),+2 额外行,因为您有当前匹配行以及 grep 正在添加的 -- 行。

【讨论】:

以上是关于如何在匹配后仅显示下一行?的主要内容,如果未能解决你的问题,请参考以下文章

Jquery在单击事件后仅显示同一类的一个项目

swift5如何在用户授予有限访问权限以选择某些照片后仅显示有限的照片库

Java套接字在写入字节数组后仅获得NUL字符

如何从 Angular 2 响应中获取所有标头?

UIImageView:如何在平移和缩放后仅捕获可见内容

当唯一 id 与查询的其他 7 个不匹配时,如何从 MySQL 查询中绘制一行