如何获取 grep 之后的第 n 行?

如何获取 grep 之后的第 n 行?

考虑以下文本文件

one 1
two 2
three 3
four 4
five 5
six 6
seven 7
eight 8

我想访问匹配行之后的第二行four。这将是以下行

six 6

然后,结果行(即上面的行)将被传输以进行进一步处理(例如,a | cut -d' ' -f2)。

有没有办法在 bash 和其他典型实用程序中做到这一点?(否则我将用 Python 编写脚本)

编辑:在我的特定情况下,(举个例子)的出现four保证是唯一的。但答案显示了有趣的扩展情况,但事实并非如此。

答案1

前两个答案并没有错,但我想让你知道,在一次sed调用中就可以找到模式后的第三行:

sed -n "/four/ { n; n; p }" SourceData.txt

因为单个程序可以完成这项工作,所以这比运行多个过滤器更有效率。上述命令在每次出现“four”后都会输出第三行,除非在匹配后的两行之一中再次出现这种情况(其他解决方案也不会以预期的方式处理这种情况);此外,如果模式位于文件的最后一行或倒数第二行,则不会生成任何输出,这可能是也可能不是您想要的。

仅匹配第一个实例:

sed -n "/four/ { n; n; p; q }" SourceData.txt

(请注意,这个答案尽可能高效,因为一旦找到匹配就结束扫描。)

我添加这个解决方案是因为它值得了解sed,尽管它的语法相当令人反感(正则表达式已经够糟糕了!),但它通常非常有用。这教程是一个很好的介绍。

答案2

注意:这个答案最初是在 OP 明确说明模式只出现一次之前写的。它被设计为不会错过任何出现的情况(除非接近结尾,所以没有“第 n 行之后”),我将保留它。如果您确定只出现一次,或者如果您只希望找到第一个,您可以考虑其他立即停止并且不解析整个输入流/文件的解决方案徒然


此解决方案打印当前行,当且仅当两行之前有匹配项。它与其他一些答案略有不同,因为它不会错过另一个匹配项,即使该匹配项在上一个匹配项之后不久发生。

awk -v delay=2 '{for (i=delay; i>=0; i--) t[i]=t[i-1]} /four/ {t[0]="m"} {if (t[delay]) print}'

只要有匹配项,信息就会存储在 中t[0]。每行t数组都会移动一次(包括移动t[-1]t[0]以重置 的值t[0])。当且仅当数组指示两行之前有匹配项时,才会打印该行。

您可以轻松设置不同的延迟(例如delay=7)或使用其他模式(例如/sda[[:digit:]]/

答案3

您可以使用以下表达式(input.txt):

grep "four" -A 2 input.txt | tail -n 1

输出为:

six 6

选项grep“-A 2”表示输出匹配行后的两行。
选项tail“-n 1”表示只1返回此结果的最后几行。

答案4

对于多次出现的情况,并假设没有行以 开头--

( grep -A 2  pattern data.txt; echo '--' ) | grep -E -B1 '^--' | grep -Ev '^--'

慢动作:

  • ( grep -A 2 pattern data.txt; echo '--' )打印模式和接下来的两行,并--在组之间插入一行。echo '--'确保最后一组后面也跟着--
  • grep -E -B1 '^--'打印分隔符和之前的行(这就是我们要找的)
  • grep -Ev '^--'删除分隔符,仅留下我们正在寻找的行。

相关内容