sed:返回上次出现的匹配,直到文件结束

时间:2011-10-11 10:45:39

标签: regex bash sed

使用sed,如何返回匹配的最后一次出现,直到文件结束? (仅供参考,这已经简化)

到目前为止,我已经尝试过:

sed -n '/ Statistics |/,$p' logfile.log

返回第一场比赛开始的所有线路(几乎整个文件)

我也试过了:

$linenum=`tail -400 logfile.log | grep -n " Statistics |" | tail -1 | cut -d: -f1`
sed "$linenum,\$!d" logfile.log

这有效,但在一个命令中无法通过ssh连接工作,真的需要将它们放在一个管道中。

日志文件的格式如下:

(有每分钟写入日志文件的子数据的统计标头,此命令的目的是返回最新的Statistics标头以及标头之后发生的任何相关错误)

Statistics |
   Stuff
   More Stuff
   Even more Stuff
Statistics |
   Stuff
   More Stuff
Error: incorrect value
Statistics |
   Stuff
   More Stuff
   Even more Stuff
Statistics |
   Stuff
Error: error type one
Error: error type two

EOF

返回需要:

Statistics |
   Stuff
Error: error type one
Error: error type two

5 个答案:

答案 0 :(得分:15)

您的示例脚本在统计信息之前有一个空格,但您的示例数据似乎没有。这有一个正则表达式,假设统计数据处于起始行;调整,如果那是不正确的。

sed -n '/^Statistics |/h;/^Statistics |/!H;$!b;x;p'

当您看到统计信息时,请使用当前行(h)替换保留空间。否则,附加到保留空间(H)。如果我们不在文件末尾,请在此处停止(b)。在文件末尾,打印出保留空间(x检索保留空间的内容; p打印)。

sed脚本中,命令可选地以“地址”为前缀。最常见的是这是一个正则表达式,但它也可以是一个行号。地址/^Statistics |/选择与正则表达式匹配的所有行; /^Statistics |/!选择与正则表达式不匹配的行;并且$!匹配除文件中最后一行之外的所有行。对所有输入行都执行没有显式地址的命令。

编辑更详细地解释一下脚本,并添加以下内容。

请注意,如果您需要使用ssh将其传递给远程主机,则需要额外的引用级别。如果它过于复杂,一种可能的解决方法是将此脚本存储在远程主机上,而只是ssh remotehost path/to/script。另一种可能的解决方法是更改​​寻址表达式,使它们不包含任何感叹号(这些在命令行中存在问题,例如在Bash中)。

sed -n '/^Statistics |/{h;b};H;${x;p}'

这也有点简单!

第三种可能的解决方法,如果你的ssh管道的stdin与其他东西没有关系,就是从本地主机管道脚本。

echo '/^Statistics |/h;/^Statistics |/!H;$!b;x;p' |
ssh remotehost sed -n -f - file

答案 1 :(得分:14)

如果您有tac可用:

tac INPUTFILE | sed '/^Statistics |/q' | tac

答案 2 :(得分:2)

如果您对awk解决方案感到满意,这种方式有效(除了获得额外的空白行):

awk '/^Statistics/ { buf = "" } { buf = buf "\n" $0 } END { print buf }' input.txt

答案 3 :(得分:1)

sed ':a;N;$!ba;s/.*Statistics/Statistics/g' INPUTFILE

应该有效(GNU sed 4.2.1)。

它将整个文件读取为一个字符串,然后用Statistics替换从开头到最后一个Statistics(包括单词)的所有内容,并打印剩余的内容。

HTH

答案 4 :(得分:1)

这可能也有效,上面其他人给出的sed解决方案稍微简单一点:

sed -n 'H; /^Statistics |/h; ${g;p;}' logfile.log

输出:

Statistics |
   Stuff
Error: error type one
Error: error type two
相关问题