sed 模式空间和保持空间

sed 模式空间和保持空间

我刚刚经历过这个,但我无法理解。

sed -n '1h; 1!H; ${ g; s/foo\nbar/bla\nblub/ p }' file.

其中 cat 文件是:

 foo
 foo
 bar

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

但 sed oneliner 似乎工作正常。

答案1

@manatwork 的回答的实际原因1h;1!H,但我想添加一个可移植性说明。

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

sed -n '1h; 1!H; ${ g; s/foo\nbar/bla\
blub/p;}'

否则它在大多数实现中都无法工作sed,例如传统的 Unix 实现。

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

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

sed -n '
  :1
  $!{
   N;b1
  }
  s/foo\nbar/blah\
blup/p'

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

可移植的是,你最好使用perl

perl -0777 -ne 'print if s/foo\nbar/blah\nblup/'

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

答案2

为什么有 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

这是必要的,因为根据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.

因此,如果您仅使用H附加所有行,则第一行之前会有一个额外的换行符:

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

相关内容