:a;$!N; 是什么意思?在 sed 命令中?

Avi*_*Raj 12 sed text-processing

$ (echo hello; echo there) | sed ':a;$!N;s/\n/string/;ta'
hellostringthere
Run Code Online (Sandbox Code Playgroud)

上面的sed命令用字符串“string”替换换行符。但我不知道:a;$!N;s/\n/string/;ta单引号内的含义。我知道中间部分s/\n/string/。但我不知道 first ( :a;$!N;) 和 last ( ta) 部分的功能。

ter*_*don 18

这些是公认的神秘sed命令。具体(来自man sed):

: label
         b 和 t 命令的标签。

t label
         如果 as/// 自上一个输入行被读取并且自上一个 t 或 T 命令以来已成功完成替换,则分支到标签;如果省略标签,则分支到脚本末尾。

n N 将下一行输入读取/追加到模式空间中。

因此,您发布的脚本可以分解为(添加空格以提高可读性):

sed ':a;  $!N;  s/\n/string/;  ta'
     ---  ----  -------------  --
      |     |        |          |--> go back (`t`) to `a`
      |     |        |-------------> substitute newlines with `string`
      |     |----------------------> If this is not the last line (`$!`), append the 
      |                              next line to the pattern space.
      |----------------------------> Create the label `a`.
Run Code Online (Sandbox Code Playgroud)

基本上,这可以用伪代码编写为

while (not end of line){
    append current line to this one and replace \n with 'string'
}
Run Code Online (Sandbox Code Playgroud)

您可以通过更复杂的输入示例更好地理解这一点:

$ printf "line1\nline2\nline3\nline4\nline5\n" | sed ':a;$!N;s/\n/string/;ta'
line1stringline2stringline3stringline4stringline5
Run Code Online (Sandbox Code Playgroud)

我不确定为什么!$需要它。据我所知,您可以获得相同的输出

printf "line1\nline2\nline3\nline4\nline5\n" | sed ':a;N;s/\n/string/;ta'
Run Code Online (Sandbox Code Playgroud)

  • 我尝试将 `$!` 视为带有后缀补码运算符的地址“范围” - 所以 `$!N`(除了地址 `$` 之外的所有地方都执行 `N`)实际上与类似 `m 的语法相同,n!d`(删除除 `m` 到 `n` 行以外的所有内容)。 (4认同)