2

使用sed,我想打印文件的最后一个匹配行。我碰到

sed:返回最后一次匹配,直到文件结束

但是,我只想要匹配的线本身,而不是任何范围的线。使用该页面,我实际上想出了一个有效的命令

$ sed '/out_time=/h; $!d; x' progress.txt
out_time=00:00:07.720000

问题是为什么这会起作用,或者换句话说,这个命令中发生了什么。sed如果存在,还包括一个更简单的命令。

4

3 回答 3

4

很简单,这些是在每一行(循环)上运行的三个独立命令:

  • h命令将当前保持缓冲区替换为包含out_time=.
  • $!d删除任何不是最后一行并重新开始下一个循环。
  • x命令交换保持和模式缓冲区。

效果是最后out_time=一行被放置在保持缓冲区中,并且唯一通过$!d过滤器逃逸的行(文件的最后一行)在打印之前与该保持缓冲区交换。

将其视为以下几行的程序:

for every line in file:
    if line contains "out_time=":
        holdbuff = line
    if line is not last line of file:
        continue for loop
    swap line and holdbuff
    print line

当然,如果您拥有适合这项工作的正确工具,则可以避免整个折磨过程:

grep 'out_time=' progress.txt | tail -1
于 2013-03-12T05:34:15.037 回答
3

我想这可能被认为更简单:

sed -n '/out_time=/h; ${x;p;}' progress.txt

也可以写成:

sed -n '/out_time=/h; $x; $p' progress.txt

在所有这些中,sed只是在保持空间中保存了一条匹配行,因此当它到达文件末尾时,它找到的最后一个匹配项是在保持空间中。此时,它将保持空间拉入模式空间,然后打印它。

于 2013-03-12T05:33:14.700 回答
0

一个很晚的答案,没有使用任何管道awk(有人提到了正确的工具......):

awk '/out_time=/{last=$0} END{print last}'  progress.txt

解释:

  • /$PAT/{...}: 将匹配的事件保存到变量last中,覆盖之前的事件
  • END{...}:退出程序时执行块,在这种情况下打印的值last
于 2022-02-10T10:48:56.833 回答