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

时间:2022-03-05 22:05:19

Using sed, how do I return the last occurance of a match until the End Of File? (FYI this has been simplified)

使用sed,如何在文件结束之前返回匹配的最后一次出现?(供大家参考)

So far I've tried:

到目前为止我已经试过:

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

Which returns all lines from the first match onwards (almost the entire file)

返回从第一个匹配开始的所有行(几乎是整个文件)

I've also tried:

我也试过:

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

This works but won't work over an ssh connection in one command, really need it all to be in one pipeline.

这可以工作,但不能在一个命令的ssh连接上工作,需要所有的连接都在一个管道中。

Format of the log file is as follows:

日志文件的格式如下:

(There are statistics headers with sub data written to the log file every minute, the purpose of this command is to return the most recent Statistics header together with any associated errors that occur after the header)

(有一些统计头,每分钟都将子数据写到日志文件中,此命令的目的是返回最近的统计头,以及头之后发生的任何相关错误)

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

EOF

Return needs to be:

还需要:

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

6 个解决方案

#1


14  

If you have tac available:

如果你有tac:

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

#2


15  

Your example script has a space before Statistics but your sample data doesn't seem to. This has a regex which assumes Statistics is at beginning of line; tweak if that's incorrect.

示例脚本在统计数据之前有空格,但是示例数据似乎没有空格。这有一个正则表达式,它假设统计是在直线的开始;如果这是不正确的调整。

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

When you see Statistics, replace the hold space with the current line (h). Otherwise, append to the hold space (H). If we are not at the end of file, stop here (b). At end of file, print out the hold space (x retrieve contents of hold space; p print).

当您看到统计数据时,用当前行(h)替换保留空间(h)。否则,追加到保存空间(h)。如果我们不在文件的末尾,停止在这里(b)。在文件结束时,打印出保存空间(x检索保存空间的内容;打印页)。

In a sed script, commands are optionally prefixed by an "address". Most commonly this is a regex, but it can also be a line number. The address /^Statistics |/ selects all lines matching the regular expression; /^Statistics |/! selects lines not matching the regular expression; and $! matches all lines except the last line in the file. Commands with no explicit address are executed for all input lines.

在sed脚本中,命令可选地以“地址”作为前缀。最常见的是regex,但它也可以是行号。地址/ ^统计| /选择所有行匹配正则表达式;/ ^统计| !选择不匹配正则表达式的行;和美元!匹配文件中除最后一行之外的所有行。对所有输入行执行没有显式地址的命令。

Edit Explain the script in some more detail, and add the following.

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

Note that if you need to pass this to a remote host using ssh, you will need additional levels of quoting. One possible workaround if it gets too complex is to store this script on the remote host, and just ssh remotehost path/to/script. Another possible workaround is to change the addressing expressions so that they don't contain any exclamation marks (these are problematic on the command line e.g. in Bash).

请注意,如果需要使用ssh将其传递给远程主机,则需要附加的引用级别。如果它变得太复杂,一种可能的解决方案是将这个脚本存储在远程主机上,并且只存储ssh远程主机路径/to/script。另一个可能的解决方案是修改寻址表达式,使它们不包含任何惊叹号(这些在命令行上是有问题的,例如在Bash中)。

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

This is somewhat simpler, too!

这也比较简单!

A third possible workaround, if your ssh pipeline's stdin is not tied up for other things, is to pipe in the script from your local host.

如果您的ssh管道的stdin没有被绑定到其他东西,那么第三个可能的解决方案就是从您本地主机的脚本中导入脚本。

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

#3


3  

This might work for you:

这可能对你有用:

sed '/Statistics/h;//!H;$!d;x' file
Statistics |
   Stuff
Error: error type one
Error: error type two

#4


2  

If you're happy with an awk solution, this kinda works (apart from getting an extra blank line):

如果你对awk的解决方案很满意,那么这是可行的(除了获得额外的空行):

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

#5


1  

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

should work (GNU sed 4.2.1).

应该工作(GNU sed 4.2.1)。

It reads the whole file to one string, then replaces everything from the start to the last Statistics (word included) with Statistics, and prints what's remaining.

它将整个文件读入一个字符串,然后用统计数据替换从开始到最后的统计数据(包括单词)的所有内容,并打印剩下的内容。

HTH

HTH

#6


1  

This might also work, slightly more simple version of the sed solution given by the others above:

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

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

Output:

输出:

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

#1


14  

If you have tac available:

如果你有tac:

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

#2


15  

Your example script has a space before Statistics but your sample data doesn't seem to. This has a regex which assumes Statistics is at beginning of line; tweak if that's incorrect.

示例脚本在统计数据之前有空格,但是示例数据似乎没有空格。这有一个正则表达式,它假设统计是在直线的开始;如果这是不正确的调整。

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

When you see Statistics, replace the hold space with the current line (h). Otherwise, append to the hold space (H). If we are not at the end of file, stop here (b). At end of file, print out the hold space (x retrieve contents of hold space; p print).

当您看到统计数据时,用当前行(h)替换保留空间(h)。否则,追加到保存空间(h)。如果我们不在文件的末尾,停止在这里(b)。在文件结束时,打印出保存空间(x检索保存空间的内容;打印页)。

In a sed script, commands are optionally prefixed by an "address". Most commonly this is a regex, but it can also be a line number. The address /^Statistics |/ selects all lines matching the regular expression; /^Statistics |/! selects lines not matching the regular expression; and $! matches all lines except the last line in the file. Commands with no explicit address are executed for all input lines.

在sed脚本中,命令可选地以“地址”作为前缀。最常见的是regex,但它也可以是行号。地址/ ^统计| /选择所有行匹配正则表达式;/ ^统计| !选择不匹配正则表达式的行;和美元!匹配文件中除最后一行之外的所有行。对所有输入行执行没有显式地址的命令。

Edit Explain the script in some more detail, and add the following.

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

Note that if you need to pass this to a remote host using ssh, you will need additional levels of quoting. One possible workaround if it gets too complex is to store this script on the remote host, and just ssh remotehost path/to/script. Another possible workaround is to change the addressing expressions so that they don't contain any exclamation marks (these are problematic on the command line e.g. in Bash).

请注意,如果需要使用ssh将其传递给远程主机,则需要附加的引用级别。如果它变得太复杂,一种可能的解决方案是将这个脚本存储在远程主机上,并且只存储ssh远程主机路径/to/script。另一个可能的解决方案是修改寻址表达式,使它们不包含任何惊叹号(这些在命令行上是有问题的,例如在Bash中)。

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

This is somewhat simpler, too!

这也比较简单!

A third possible workaround, if your ssh pipeline's stdin is not tied up for other things, is to pipe in the script from your local host.

如果您的ssh管道的stdin没有被绑定到其他东西,那么第三个可能的解决方案就是从您本地主机的脚本中导入脚本。

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

#3


3  

This might work for you:

这可能对你有用:

sed '/Statistics/h;//!H;$!d;x' file
Statistics |
   Stuff
Error: error type one
Error: error type two

#4


2  

If you're happy with an awk solution, this kinda works (apart from getting an extra blank line):

如果你对awk的解决方案很满意,那么这是可行的(除了获得额外的空行):

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

#5


1  

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

should work (GNU sed 4.2.1).

应该工作(GNU sed 4.2.1)。

It reads the whole file to one string, then replaces everything from the start to the last Statistics (word included) with Statistics, and prints what's remaining.

它将整个文件读入一个字符串,然后用统计数据替换从开始到最后的统计数据(包括单词)的所有内容,并打印剩下的内容。

HTH

HTH

#6


1  

This might also work, slightly more simple version of the sed solution given by the others above:

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

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

Output:

输出:

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