sed 模式空间和保持空间

mun*_*ish 5 sed

我只是通过这个,我无法理解。

sed -n '1h; 1!H; ${ g; s/foo\nbar/bla\nblub/ p }' file.
Run Code Online (Sandbox Code Playgroud)

cat文件在哪里:

 foo
 foo
 bar
Run Code Online (Sandbox Code Playgroud)

为什么有1!H因为对我来说1h覆盖了模式空间并且1!H没有用

但是 sed one liner 似乎工作正常。

man*_*ork 8

为什么有 1!H 因为对我来说 1h 覆盖了模式空间而 1!H 没有用

不会发生覆盖,因为它们不在同一输入行上执行:

1h   # when input line number is 1, copy pattern space to hold space
1!H  # when input line number is not 1, append pattern space to hold space
Run Code Online (Sandbox Code Playgroud)

这是必要的,因为根据info sed

`H'
     Append a newline to the contents of the hold space, and then
     append the contents of the pattern space to that of the hold space.
Run Code Online (Sandbox Code Playgroud)

因此,如果您使用 justH来追加所有行,则在第一行之前会有一个额外的换行符:

bash-4.2$ seq 3 | sed -n 'H; ${g; p;}'

1
2
3
bash-4.2$ seq 3 | sed -n '1h; 1!H; ${g; p;}'
1
2
3
Run Code Online (Sandbox Code Playgroud)


Sté*_*las 8

有关的实际原因,请参阅@manatwork 的答案1h;1!H,但我想添加可移植性说明。

标准和可移植的语法应该是:

sed -n '1h; 1!H; ${ g; s/foo\nbar/bla\
blub/p;}'
Run Code Online (Sandbox Code Playgroud)

否则它在大多数sed实现中都不起作用,例如传统的 Unix 实现。

\ns命令的左侧可以理解,但是您必须在右侧使用反斜杠字符后跟实际的换行符。您还需要;s命令和之间使用},并且在p.之前没有空格。

您还可以将文件的内容存储在模式空间而不是保留空间中:

sed -n '
  :1
  $!{
   N;b1
  }
  s/foo\nbar/blah\
blup/p'
Run Code Online (Sandbox Code Playgroud)

但是对于模式和保持空间,大多数sed实现只能处理小文件,因为大多数非 GNU 实现对这些文件的大小有限(而 POSIX 只要求它们能够保存 8kiB 的数据)。

便携地,你最好使用perl

perl -0777 -ne 'print if s/foo\nbar/blah\nblup/'
Run Code Online (Sandbox Code Playgroud)

因为大小在perlGNU 中没有限制,sed但是请注意它可能会影响系统性能,因为如果您没有对每个进程的内存使用进行管理设置限制,它可能最终会使用所有系统内存。