理解sed保持空间工作流程

理解sed保持空间工作流程,sed,Sed,我想打印出包含一个或多个整数的文件的最后一行。“Hippo 9991”在下面的示例中。我试图通过gsed-n-r'/[0-9]+//h来实现这一点;x$p'命令,但这不太有效: $ cat testfile dog lion 34 elephant tiger 7 hippo 9991 zebra gepard cat $ cat testfile | gsed -n -r '/[0-9]+/h;x;$p' gepard $ 谁能解释一下gsed-n-r'/[0-9]+/h到底是什么;x$

我想打印出包含一个或多个整数的文件的最后一行。“Hippo 9991”在下面的示例中。我试图通过
gsed-n-r'/[0-9]+//h来实现这一点;x$p'
命令,但这不太有效:

$ cat testfile 
dog
lion 34
elephant
tiger 7
hippo 9991
zebra
gepard
cat
$ cat testfile | gsed -n -r '/[0-9]+/h;x;$p'
gepard
$ 

谁能解释一下gsed-n-r'/[0-9]+/h到底是什么;x$p'是吗?据我所知,它应该从行中删除尾随的新行字符,并将行读入模式空间。然后,如果模式空间中的行包含一个或多个整数,则通过替换保持空间中以前的数据将该行放入保持空间。重复此循环,直到打印最后一行。显然,我没有正确理解这一点。除了正确的答案,我还想了解sed的工作流程。

我无法帮助您使用
sed
版本,但是
awk
解决方案可以轻松做到这一点

awk '/[0-9]+/ {f=$0} END {print f}' file
hippo 9991

以下是我的作品:

sed -n -r '/[0-9]+/ {h;x}; ${x;p}'

仅当整数存在时,才希望同时运行
h
x
,在您的示例中,每次运行
x
。最后,您不想打印最后一行,而是要打印最后存储的行,因此您必须再次交换它们。

您几乎拥有了它。以下是脚本的作用:

/[0-9]+/h     # if line contains a number, save the line to hold space
x             # swap content of pattern space and hold space
$p            # when on the last line print pattern space
保存线以保留空间,然后将其交换回图案空间。图案空间和保持空间的内容可以如下所示:

Line      Command     Pattern Space       Hold Space
~~~~    ~~~~~~~~~~~   ~~~~~~~~~~~~~       ~~~~~~~~~~
 1       /[0-9]+/h     dog                   
 1           x                             dog                 
 2       /[0-9]+/h     lion 34             lion 34
 2           x         lion 34             lion 34
 3       /[0-9]+/h     elephant            lion 34
 3           x         lion 34             elephant
 4       /[0-9]+/h     tiger 7             tiger 7
 4           x         tiger 7             tiger 7
 .
 .
 .
 $       /[0-9]+/h     cat                 geopard
 $           x         geopard             cat
 $           p         geopard             cat
您真正想要的是仅在到达输入文件的最后一行时交换内容。您可以通过将
x
p
命令分组来执行此操作:

gsed -n -r '/[0-9]+/h; $ {x;p}' testfile
输出:

hippo 9991
相应的图案空间和保持空间序列现在为:

Line      Command     Pattern Space       Hold Space
~~~~    ~~~~~~~~~~~   ~~~~~~~~~~~~~       ~~~~~~~~~~
 1       /[0-9]+/h     dog                   
 2       /[0-9]+/h     lion 34             lion 34
 3       /[0-9]+/h     elephant            lion 34
 4       /[0-9]+/h     tiger 7             tiger 7
 .
 .
 .
 $       /[0-9]+/h     cat                 hippo 9991
 $           x         hippo 9991          cat
 $           p         hippo 9991          cat
我会:

 sed -n -r '/[0-9]+/{h}; ${x;p}' file 
h
用当前(匹配)行覆盖保留空间 当直到最后一行(
$
)时,我们(
x
)交换图案/保留空间,并打印保留位置的内容,这将是图案的最后匹配行
[0-9]+

,这可能适用于您(GNU-sed):

如果一行包含一个数字,则将其移入保留空间(以前移入的行将被覆盖!)。除最后一行之外的所有行都被删除(删除的行永远无法打印)。在最后一行上,交换到保留空间。程序的自然流程打印包含数字的最后一行,无需选择

grep [0-9] testfile | tail -1

缺点是我们无法了解“sed”,但要简单得多。

谢谢您的解释!难道不可能进一步简化这个问题,比如
gsed-n-r'/[0-9]+//h${x;p}'
?这将在每一行包含整数时覆盖保留空间,一旦到达最后一行,它将用保留空间交换图案空间并打印。@Martin:是的,似乎有效(针对文件测试,搜索的行在末尾和中间)。
grep [0-9] testfile | tail -1