在原地编辑文件的sed命令
sed命令是一个强大的文本处理工具,可以用来编辑文件。其中的一个常用选项是-i,它可以让我们在原文件中直接进行编辑,而不需要输出到新文件中。然而,在不同的操作系统中,使用这个选项的方式略有不同。
在大多数操作系统中,我们可以使用如下方式使用sed的-i选项进行编辑:
sed -i 's/STRING_TO_REPLACE/STRING_TO_REPLACE_IT/g' filename
然而,在macOS中,我们需要使用如下方式:
sed -i '' 's/STRING_TO_REPLACE/STRING_TO_REPLACE_IT/g' filename
某些情况下可以在系统上编译GNU sed来解决这个问题,示例命令如下:
sed -i "s/STRING_TO_REPLACE/STRING_TO_REPLACE_IT/g" <file>
还某些情况下,可以使用创建临时文件的方式来解决这个问题。首先创建一个临时文件,然后将编辑后的内容写入临时文件,最后将临时文件重命名为原文件名。
此外,还某些情况下在Windows上使用Git时可能会出现问题,Git会误以为整个文件都发生了变化。因此,在使用sed的-i选项时,需要注意检查换行符的问题。
在一些操作系统中,比如Sun的sed,是不支持-i选项的。
还某些情况下使用-i选项的一个主要好处是速度更快,相比于使用shell重定向,直接在原文件中编辑可以提高速度。
最后,有人提出了一个问题,是否有一种跨平台的方式来使用相同的语法进行编辑。对此,建议先创建一个临时文件进行编辑,然后再重命名和修改权限。
sed的-i选项在不同的操作系统中使用方式略有不同,但我们可以通过编译GNU sed、创建临时文件或者使用其他的解决方案来解决这个问题。
在OS X上运行sed编辑文件时可能会出现奇怪的错误,比如"invalid command code"或其他奇怪的错误。为了解决这个问题,可以尝试以下方法:
sed -i '' -e "s/STRING_TO_REPLACE/STRING_TO_REPLACE_IT/g" <file>
这是因为在OSX版本的sed中,-i选项需要一个扩展参数,所以你的命令实际上被解析为扩展参数,文件路径被解释为命令代码。来源:https://stackoverflow.com/a/19457213
这是OS X的另一个怪异之处。幸运的是,通过brew install gnu-sed以及PATH,你可以使用GNU版本的sed。谢谢你提到这个问题,这确实让人困惑。
在一些系统中,sed
无法直接编辑文件,这时更好的解决方法是使用perl
:perl -pi -e 's/foo/bar/g' file.txt
。尽管这会创建一个临时文件,但它会替换原文件,因为没有指定任何后缀/扩展名。
它不仅会创建一个临时文件,还会破坏硬链接(例如,它会用一个同名的新文件替换原文件,而不是更改文件内容)。有时这是期望的行为,有时是可以接受的,但当一个文件有多个链接时,这几乎总是错误的行为。
并非所有系统都安装了perl,这时就需要使用管道来解决。请参考下面的回答。
:我认为没有安装Perl的系统是有问题的。当需要提升权限并且必须使用sudo
时,一条命令胜过一系列命令。在我看来,问题是如何避免手动创建和重命名临时文件,而不必安装最新的GNU或BSD sed
。只需使用Perl即可。
不是对原问题的回答。
:真的吗?如果仔细阅读问题,你就会明白OP试图避免像sed 's/foo/bar/g' file.txt > file.tmp && mv file.tmp file.txt
这样的操作。只因为原地编辑使用了临时文件进行重命名,不意味着他/她必须在没有这个选项时执行手动重命名。还有其他工具可以实现他/她想要的效果,而Perl是显而易见的选择。这不是对原问题的回答吗?
因为回答太主观,所以我给了负分。OP问了如何使用sed完成这个任务。
_arias:你说得对,他确实问了。但是在Solaris系统中,他不能使用sed
实现他想要的效果。这个问题实际上是一个非常好的问题,但由于那些不能阅读手册或懒得真正阅读SO上的问题的人的存在,它的价值已经降低了。
“而Perl是显而易见的选择”... <咳嗽> - 我尊敬地认为Perl不再是显而易见的选择(尽管曾经是)。在我看来,Python和Ruby已经取代了Perl。顺便说一句,OP想要一个sed的解决方法。
:如果我没记错,Solaris默认安装了Perl,但没有安装Python或Ruby。而且如我之前所说,OP不能使用Solaris的sed来达到期望的结果。
- 谢谢提醒,我忽略了Solaris的要求。