为什么“sed -n -i”删除现有的文件内容?

问题描述:

运行Fedora 25服务器版。 sed --version给我sed (GNU sed) 4.2.2以及通常的版权和联系信息。我已经创建了一个文本文件sudo vi ./potential_sed_bug。 VI显示该文件的内容(与:set list启用)为:为什么“sed -n -i”删除现有的文件内容?

don't$ 
delete$ 
me$ 
please$ 

我然后运行以下命令:

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

在我们讨论的结果;这里是什么sed man page说:

-n,--quiet,--silent 抑制模式空间的自动打印

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

我也看了other sed command references了解如何追加sed。根据我对我所做的研究的理解;生成的文件内容应该是:

don't 
delete 
me 
please 
testing 

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

testing 

在这种差异的光,是我,我跑不正确或命令的理解是有sed /环境有问题吗?

TL;博士

  • 不要使用-n-i:除非你在sed脚本中使用明确的输出命令,什么都不会被写入文件。

  • 使用-i产生没有标准输出(终端)的输出,所以没有什么多余的,你需要做的,使你的命令安静。


默认情况下,sed自动打印(可能被修改)输入线到任何其输出目标是,不论是隐含的或显式指定:通过默认,向标准输出(终端,除非重定向) ;与-i,到最终替换输入文件的临时文件

两种案件,-n抑制这个自动打印,这样 - 除非你使用显式输出功能,如p或者,你的情况,a - 什么被打印到stdout /写入临时文件。

  • 注意,自动打印适用于所谓的图案空间,这是其中(可能被修改)输入被保持;明确的输出功能,例如paic打印到图案空间(潜在的后续修改),它们打印直接向目标流/文件,这就是为什么a\testing能够产生输出,尽管使用-n

注意,与-ised的隐式印刷/显式输出指令打印到临时文件,而不是也到stdout,因此使用-i一个命令是总是安静相对于标准输出(端子)输出 - 没有什么额外的你需要做的。


为了给出一个具体的例子(GNUsed语法)。

由于使用-i是偶然的问题,为简单起见,我省略了它。请注意,-i首先打印到临时文件,其中,完成后,替换原来的。这与陷阱,尤其是符号链接的潜在破坏;看到我的this answer的下半部分。

# 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 
+0

@AMemberofDollars:这样做的缺点:处理的顺序没有改变,是的,临时文件首先被写入,只有在完成它取代原来的 - 请我的更新。 – mklement0

+1

@stevesliva:我明白了,谢谢。我已经相应地更新了答案。 – mklement0

+1

有趣的是,我一直认为'sed -e cmd1 | sed -e cmd2'相当于'sed -e cmd1 -e cmd2',但是如果由于某种原因你想要修改的内容是你正在追加的内容,那么这个区域实际上就是想要sed到sed的。我想'n'和'q'其他命令也会打破这种等价性。 – stevesliva