sed 命令`n` 和`b` 之间有什么区别?

Wil*_*ard 5 sed

除了明显的语法点b可以接受标签而不能接受标签n,并且要在b没有标签的情况下使用,您需要将其放置在传递的参数的末尾-e(至少对于单行程序)...ab没有label 和 ann似乎做同样的事情。

这真的是真的,还是有我没有注意到的细微差别?他们在什么条件下做同样的事情,在什么条件下他们不做?

Joh*_*024 6

这两个例子是相同的,只是n被替换了b。可以看到输出不同:

$ echo $'1\n2\n3' | sed 's/./AA/; n; s/./BB/'
AA
BB
AA
$ echo $'1\n2\n3' | sed 's/./AA/; b; s/./BB/'
AA
AA
AA
Run Code Online (Sandbox Code Playgroud)

b分支到命令的末尾。 n继续执行剩余的命令。因此,对于bs/./BB/永远不会执行替换。使用n,每隔一行执行一次。

(上述命令是使用 GNU sed 运行的。使用 BSD/OSX sed,正如 OP 所指出的,需要对代码格式进行一些小的更改。)


don*_*sti 5

好吧,让我们看看...
牧场b命令:

[2addr]b[label]
    Branch to :label. If label is not specified, branch to the end of the script.
Run Code Online (Sandbox Code Playgroud)

外部n命令:

[2addr]n
    If auto-print is not disabled, print the pattern space, then, regardless,
    replace the pattern space with the next line of input. If no next line of
    input is available, branch to the end of the script.
Run Code Online (Sandbox Code Playgroud)

所以这里的主要区别是:

b无条件分支到脚本末尾
n如果没有更多输入,则仅分支到脚本末尾

假设输入如下:

fdue
four
four
fdue
four
Run Code Online (Sandbox Code Playgroud)

我想替换为ft但仅在匹配的行上替换为four,而在所有其他行上替换ui。一种方法是

sed '/four/{s/f/t/;b;};s/u/i/' infile
Run Code Online (Sandbox Code Playgroud)

输出如预期的那样

fdie
tour
tour
fdie
tour
Run Code Online (Sandbox Code Playgroud)

n现在,让我们看看使用而不是时会发生什么b

fdie
tour
foir
fdie
tour
Run Code Online (Sandbox Code Playgroud)

第二行匹配four被编辑为foir而不是tour因为简单的原因n不会返回到脚本的顶部。相反,处理s该行之后的命令n甚至认为这不是有意的。然而,在最后一行,仅进行了第一次替换,因此不再执行 s后面的命令。n

总而言之,如果满足以下条件,这两个命令在功能上是等效的:

  • 脚本正在处理最后一行输入(在执行之前n)或
  • 无论如何, 引入的下一行n不应由n1之前的命令编辑(换句话说,下一行不是与 关联的地址b

确实,n打印当前模式空间并拉入下一行,但b单独也具有相同的效果:分支到脚本末尾意味着自动打印(除非sed使用 调用-n,在这种情况下n也不会打印),然后自动读取在下一行输入中。正如我所说,主要区别在于n不会跳转到脚本末尾(并且也不会返回到脚本顶部):sed仅执行其余命令 - 如果有的话(如果不在最后一行) 。


1
这些命令不会被执行,因为正如我所说,n不会返回到脚本的顶部;此外,其余命令可能会编辑该行,这是不应该发生的事情。