为什么带有标志 p 的 sed 替换命令会打印两次修改后的输出?

为什么带有标志 p 的 sed 替换命令会打印两次修改后的输出?

我的 a.txt 包含以下内容:

apple
123
pear
1234

如果我运行下面的命令,

sed 's/123/AAA/p' a.txt

我以为我会得到

apple
123
AAA
pear
1234
AAA4

因为 sed 默认会自动打印每一行。我原本期望修改后的输出是在模式空间中被修改之后。但我的实际输出打印了两次替换:

apple
AAA
AAA
pear
AAA4
AAA4

这是为什么?

答案1

sed 's/123/AAA/p' a.txt

此表达式包含两个命令

  • s/123/AAA/意思是,找到带有 的行,123并在出现 的行中将其替换123AAA。默认情况下,sed打印每一行,因此,整个流都会打印修改内容

  • p意思是打印模式空间。在我们调用 的地方p,模式空间包含修改后的行,因此再次打印它们。

当我们只想打印由 发现并因此发生改变的流的行时,s和的组合p通常与 一起使用。-ns

命令的顺序很重要。在您的命令中,如果您p先输入,它将打印未修改的流,接近您的预期:

$ sed 'p;s/123/AAA/' a.txt
apple
apple
123
AAA
pear
pear
1234
AAA4

这里当我们调用时p,模式空间是整个文件,因为我们没有指定它的任何部分,并且它没有被更改。该s命令还会打印整个文件,但也会对其进行修改,因此我们会看到两次流,一次是修改的,一次是未修改的。1

因此,也许认为表达式中的命令sed是从左到右累积应用的会有所帮助,并且正如steeldriver所说,在这种情况下得到的输出是由于p在循环结束时应用的,之后s已用于选择和修改文件的一部分。


1最初,我在这里使用的命令是sed 'ps/123/AAA/' a.txt。正如mxmlnkn 的评论,此命令在 GNU 中不起作用sed。我一直在使用 BusyBox sed(在 Android 上的 Termux 中),并且没有在sedUbuntu 上的 GNU 中正确测试该命令(糟糕!)。但有趣的是,GNUsed与其他命令不同,在这里需要分号。

相关内容