b
除了可以接受标签而n
不能接受标签的明显语法点之外,并且要在没有标签的情况下使用,您需要将其放置在通过(至少对于单行)b
传递的参数的末尾...a没有 a label 和 an似乎做了完全相同的事情。-e
b
n
这是真的吗?还是有我没注意到的细微差别?在什么条件下它们会做同样的事情,在什么条件下它们不会做同样的事情?
答案1
这两个例子是相同的,只是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
b
分支到命令的末尾。 n
继续执行其余命令。因此,对于b
,替换s/./BB/
永远不会被执行。使用 时n
,每隔一行执行一次。
(上述命令是使用 GNU sed 运行的。对于 BSD/OSX sed,正如 OP 所指出的,需要对代码格式进行一些细微的更改。)
答案2
好吧,让我们看看...
牧场b
命令:
[2addr]b[label]
Branch to :label. If label is not specified, branch to the end of the script.
外部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.
所以这里的主要区别是:
b
无条件分支到脚本末尾
n
如果没有更多输入,则仅分支到脚本末尾
假设输入如下:
fdue
four
four
fdue
four
我想替换f
为t
,但仅在匹配的行上替换为four
,而在所有其他行上替换u
为i
。一种方法是
sed '/four/{s/f/t/;b;};s/u/i/' infile
输出如预期的那样
fdie
tour
tour
fdie
tour
现在,让我们看看使用n
而不是时会发生什么b
:
fdie
tour
foir
fdie
tour
第二行匹配four
被编辑为foir
而不是tour
因为简单的原因n
不会返回到脚本的顶部。相反,处理该行s
之后的命令n
甚至认为这不是有意的。然而,在最后一行,仅进行了第一次替换,因此不再执行 s
后面的命令。n
总而言之,如果满足以下条件,这两个命令在功能上是等效的:
- 该脚本正在处理最后一行输入(前执行
n
) 或 - 无论如何,引入的下一行不应由1
n
之前的命令编辑(换句话说,下一行不是与 关联的地址)n
b
确实,n
打印当前模式空间并拉入下一行,但b
单独也具有相同的效果:分支到脚本末尾意味着自动打印(除非sed
使用 调用-n
,在这种情况下n
也不会打印),然后自动读取在下一行输入中。正如我所说,主要区别在于n
不会跳转到脚本末尾(并且也不会返回到脚本顶部):sed
只需执行其余命令 - 如果有的话(如果不在最后一行)。
1
这些命令不会被执行,因为正如我所说,n
不会返回到脚本的顶部;此外,其余命令可能会编辑该行,这是不应该发生的事情。
答案3
“分支”命令 ( b
) 分支到编辑脚本中的预定义标签,如果没有标签,则分支到脚本末尾,而“下一个”命令 ( n
) 读取下一行输入。 “next”命令还在读取下一行之前输出当前模式空间(通常是刚刚读取的行),除非已使用 抑制输出-n
。
它们是两个不同的编辑命令,执行两种不同的操作。 “next”命令不会导致分支到脚本末尾,并且“branch”命令不会输出当前模式空间或自行读取任何新行。
一个简单的例子(使用 GNU sed
):
$ cat lines
1
2
3
4
5
$ gsed -n '3{n;p;p;}' lines
4
4
对于第三行,脚本将读取下一行并将其输出两次:第四行打印两次。
$ gsed -n '3{b;p;p;}' lines
这不会生成任何输出,因为脚本将分支到“print”( p
) 命令。
运行时没有-n
:
$ gsed '3{n;p;p;}' lines
1
2
3
4
4
4
5
第三行是n
脚本中的命令输出的。第四行输出三次,两次是读完下一行p
后脚本中的两次,一次是默认命令。 n
p
$ gsed '3{b;p;p;}' lines
1
2
3
4
5
这些行都是由默认p
命令输出的,因为“branch”命令将绕过p
脚本中的这两行。
总结一下:n
加载下一行并继续处理下一条指令,同时b
跳到指定分支(如果已命名)或脚本末尾。在任何一种情况下,当 sed 到达脚本末尾时,任何剩余的输入都会像往常一样从脚本的开头进行处理。