sed 脚本在最后一次出现匹配后打印 n 行

sed 脚本在最后一次出现匹配后打印 n 行

这里是一个链接,用于打印最后一次出现的匹配项之后的所有行。

但是,我只想在最后一次出现匹配后打印两行。我该怎么做呢?

答案1

你可以使用ed

printf '%s\n' '?pattern?+1, ?pattern?+2 p' | ed -s file

ed这会向stdin发送一个命令;读取文件时,该-s标志禁止输出字节计数。该命令分解如下:

  • ... , ... p-- 打印给定 (..., ...) 地址范围内的行
  • ?pattern?+1-- 向后搜索然后pattern添加一个
  • ?pattern?+2-- 向后搜索然后pattern添加两个

当前默认为文件的最后一行,因此这些搜索会查找pattern文件中最后一次出现的 。然后,偏移量会选择后面的两条线。

答案2

使用 GNUgreptailαГsнιη 的示例文件:

$ cat file
====
1
2
3
4
====
11
22
33
====
111
222
333
444
====
1111
2222
3333

$ grep  -A2 "====" file  | tail -n2
1111
2222

告诉打印匹配行(在本例中,我们-A2正在grep搜索====)及其后面的两行。然后,tail -n2仅打印最后两行。

如果您的文件非常大,您可以通过从文件末尾读取tac并反转逻辑来加快速度:

$ tac file | grep -m1 -B2 "====" | tac |tail -n2
1111
2222

答案3

使用sed并假设您想要两条线最后一个匹配pattern(并且另外假设每条匹配行pattern与任何其他匹配行至少相隔两行):

$ cat file
a
b       pattern
c       the 1st
d       the 2nd
e       the 3rd
1
2
3       pattern
4       the first
5       the second
6       the third
7
$ sed -n -e '/pattern/ { n; N; h; }' -e '$ { g; /./p; }' file
4       the first
5       the second

只要匹配,该sed命令就会读取 with 中的下一行。之后的行被附加到缓冲区,并且两行都被复制到保留空间(覆盖过去存储在那里的任何内容)。npatternNh

当我们到达最后一行时,我们得到保留空间,其中现在包含行匹配之后的最新两行,或者如果没有匹配pattern则为空。pattern如果缓冲区不为空,则输出。

为了得到匹配行之后的行pattern,使用n; N; N; h;代替n; N; h;

获取行匹配后的三行pattern(现在假设匹配行至少相距三行):

$ sed -n -e '/pattern/ { n; N; N; h; }' -e '$ { g; /./p; }' file
4       the first
5       the second
6       the third

pattern消除了行匹配相距较远的需要,我们需要检查pattern我们读取的“后面的行”是否匹配,如果匹配,则从那里重新开始。

sed -n -e ':a' -e '/pattern/ { n; /pattern/ba; N; /pattern/ba; h; }' -e '$ { x; /./p; }' file

答案4

GNU sed在扩展正则表达式模式下-E 将 shell 变量更改为您想要查看的行数。

n=2
sed -Ee '
  /\n/q
  /pattern/{
    :loop
      $d;N
    /(.*\n){'"$n"'}/!bloop
    x
  }
  $!d;x
  /\n.*\n/D
  s/.*\n//p;d
' file
  • 找到图案线后,设置一个循环以在图案空间中累积线。
  • 当看到图案线之后的第n条线时停止(不包括图案线)。
  • 将这 n+1 行存储在保留中,如果未达到 eof,则重新开始搜索下一个可能出现的模式。
  • 最后在 eof 处,检索保留空间数据并从中剥离第一行(模式行)。

相关内容