使用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
答案 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