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)
这是为什么?
sed 's/123/AAA/p' a.txt
Run Code Online (Sandbox Code Playgroud)
此表达式包含两个命令
s/123/AAA/意思是,在它出现的那些行上查找第一个实例中的行123并替换123为AAA。默认情况下,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与其他软件的不同之处在于这里需要一个分号。