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

Min*_*t.K 4 command-line bash sed

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

apple
123
pear
1234
Run Code Online (Sandbox Code Playgroud)

如果我在下面运行这个命令,

sed 's/123/AAA/p' a.txt
Run Code Online (Sandbox Code Playgroud)

我以为我会得到

apple
123
AAA
pear
1234
AAA4
Run Code Online (Sandbox Code Playgroud)

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

apple
AAA
AAA
pear
AAA4
AAA4
Run Code Online (Sandbox Code Playgroud)

这是为什么?

Zan*_*nna 8

sed 's/123/AAA/p' a.txt
Run Code Online (Sandbox Code Playgroud)

此表达式包含两个命令

  • s/123/AAA/意思是,在它出现的那些行上查找第一个实例中的行123并替换123AAA。默认情况下,sed打印每一行,因此,整个流都与修改一起打印

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

的组合s,并p通常与使用-n,当我们只想打印由被发现的流线s,并因此改变。

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

$ sed 'p;s/123/AAA/' a.txt
apple
apple
123
AAA
pear
pear
1234
AAA4
Run Code Online (Sandbox Code Playgroud)

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

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


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

  • `sed 'ps/123/AAA/' a.txt` 对我不起作用。它给出了`sed: -e expression #1, char 2: extra characters after command`。注意`sed -n 'p; s/123/AAA/p' a.txt` 产生了问题中预期的输出。 (2认同)