6

运行 Fedora 25 服务器版。sed --version给了我sed (GNU sed) 4.2.2通常的版权和联系信息。我创建了一个文本文件sudo vi ./potential_sed_bug。Vi 将这个文件的内容(:set list启用)显示为:

don't$
delete$
me$
please$

然后我运行以下命令:

sudo sed -n -i.bak /please/a\testing ./potential_sed_bug

在我们讨论结果之前;这是sed 手册页的内容:

-n, --quiet, --silent 禁止自动打印模式空间

-i[SUFFIX], --in-place[=SUFFIX] 就地编辑文件(如果提供扩展名,则进行备份)。默认操作模式是断开符号链接和硬链接。这可以通过 --follow-symlinks 和 --copy 进行更改。

我还查看了其他 sed 命令参考以了解如何附加 sed。根据我对我所做研究的理解;生成的文件内容应为:

don't
delete
me
please
testing

但是,运行sudo cat ./potential_sed_bug会给我以下输出:

testing

鉴于这种差异,我对我运行的命令的理解是否不正确,或者 sed/环境是否存在错误?

4

1 回答 1

8

tl;博士

  • 不要使用-nwith -i: 除非您在sed脚本中使用显式输出命令,否则不会将任何内容写入您的文件。

  • 使用不会-i产生标准输出(终端)输出,因此您不需要做任何额外的事情来使您的命令安静。


默认情况下,sed自动将(可能已修改的)输入行打印到其输出目标,无论是隐含的还是明确指定的:默认情况下,打印到stdout(终端,除非重定向);与-i, 到最终替换输入文件的临时文件。

这两种情况下,都会-n 抑制这种自动打印,因此 - 除非您使用显式输出功能,例如,p或者,在您的情况下,a-没有任何内容被打印到标准输出/写入临时文件。

  • 请注意,自动打印适用于所谓的模式空间,这是保存(可能已修改)输入的地方;显式输出函数,例如p, a,i并且c不打印到模式空间(用于潜在的后续修改),它们直接打印目标流 / 文件,这就是为什么a\testing能够产生输出,尽管使用-n.

请注意,使用-i,sed的隐式打印/显式输出命令打印到临时文件,而不打印到标准输出,因此使用的命令-i对于标准输出(终端)输出总是安静的 - 您无需做任何额外的事情。


举一个具体的例子(GNU sed语法)。

由于使用-i是附带的问题,为了简单起见,我省略了它。请注意,首先-i打印到一个临时文件,该文件在完成时会替换原始文件。这带来了陷阱,尤其是符号链接的潜在破坏;请参阅我的这个答案的下半部分。

# Print input (by default), and append literal 'testing' after 
# lines that contain 'please'.
$ sed '/please/ a testing' <<<$'yes\nplease\nmore'
yes
please
testing
more

# Adding `-n` suppresses the default printing, so only `testing` is printed.
# Note that the sequence of processing is exactly the same as without `-n`:
# If and when a line with 'please' is found, 'testing' is appended *at that time*.
$ sed -n '/please/ a testing' <<<$'yes\nplease\nmore'
testing

# Adding an unconditional `p` (print) call undoes the effect of `-n`.
$ sed -n 'p; /please/ a testing' <<<$'yes\nplease\nmore'
yes
please
testing
more
于 2017-03-07T01:59:50.047 回答