我试图找出是否有可能在单个sed命令中编辑文件,而无需手动将编辑后的内容流式传输到新文件中,然后将新文件重命名为原始文件名。我尝试了该-i
选项,但是我的Solaris系统说这-i
是非法的选项。有其他方法吗?
我试图找出是否有可能在单个sed命令中编辑文件,而无需手动将编辑后的内容流式传输到新文件中,然后将新文件重命名为原始文件名。我尝试了该-i
选项,但是我的Solaris系统说这-i
是非法的选项。有其他方法吗?
Answers:
的 -i
选项将编辑后的内容流式传输到一个新文件中,然后无论如何都要在幕后对其进行重命名。
例:
sed -i 's/STRING_TO_REPLACE/STRING_TO_REPLACE_IT/g' filename
和
sed -i '' 's/STRING_TO_REPLACE/STRING_TO_REPLACE_IT/g' filename
在macOS上。
sed -i "s/STRING_TO_REPLACE/STRING_TO_REPLACE_IT/g" <file>
在sed
无法编辑文件的系统上,我认为更好的解决方案是使用perl
:
perl -pi -e 's/foo/bar/g' file.txt
尽管这确实创建了一个临时文件,但是由于提供了空的后缀/扩展名,因此它将替换原始文件。
sudo
。在我看来,问题在于如何避免在无需安装最新GNU或BSD的情况下手动创建和重命名临时文件sed
。只需使用Perl。
sed 's/foo/bar/g' file.txt > file.tmp && mv file.tmp file.txt
。仅仅因为就地编辑会使用临时文件进行重命名,并不意味着他/她在选项不可用时必须执行手动重命名。还有其他工具可以满足他/她的需求,Perl是显而易见的选择。这不是原始问题的答案吗?
sed
。这个问题实际上是一个很好的问题,但由于无法阅读手册页或不愿意在此处实际阅读问题的人而降低了其价值。
请注意,在OS X上,运行此命令时可能会遇到奇怪的错误,例如“无效的命令代码”或其他奇怪的错误。要解决此问题,请尝试
sed -i '' -e "s/STRING_TO_REPLACE/STRING_TO_REPLACE_IT/g" <file>
这是因为在OSX版本的上sed
,该-i
选项需要一个extension
参数,因此您的命令实际上被解析为extension
参数,而文件路径被解释为命令代码。资料来源:https : //stackoverflow.com/a/19457213
brew install gnu-sed
以及PATH
可以使您使用sed的GNU版本。感谢您的提及;明确的头部抓痒器。
以下在我的Mac上正常工作
sed -i.bak 's/foo/bar/g' sample
我们在示例文件中用bar替换了foo。原始文件的备份将保存在sample.bak中
要编辑内联而不进行备份,请使用以下命令
sed -i'' 's/foo/bar/g' sample
需要注意的一件事是,sed
不能仅凭sed自己写文件就是充当“流”(即stdin,stdout,stderr和其他>&n
缓冲区,套接字等的管道)的编辑器。考虑到这一点,您可以使用另一个命令tee
将输出写回到文件中。另一种选择是通过将内容传送到中创建补丁diff
。
三通法
sed '/regex/' <file> | tee <file>
补丁方式
sed '/regex/' <file> | diff -p <file> /dev/stdin | patch
更新:
另外,请注意,patch将使文件从diff输出的第1行进行更改:
补丁程序不需要知道要访问哪个文件,因为可以在diff输出的第一行找到它:
$ echo foobar | tee fubar
$ sed 's/oo/u/' fubar | diff -p fubar /dev/stdin
*** fubar 2014-03-15 18:06:09.000000000 -0500
--- /dev/stdin 2014-03-15 18:06:41.000000000 -0500
***************
*** 1 ****
! foobar
--- 1 ----
! fubar
$ sed 's/oo/u/' fubar | diff -p fubar /dev/stdin | patch
patching file fubar
/dev/stdin 2014-03-15
,1月7日回答 -您是外行吗?
/dev/stdin
不存在使用msysgit的功能,因此您必须替换/dev/stdin
为'-',即没有引号的单个连字符,因此以下命令应该可以使用:$ sed 's/oo/u/' fubar | diff -p fubar -
和$ sed 's/oo/u/' fubar | diff -p fubar - | patch
patch
也不会截断。我认为将输出保存到另一个文件,然后cat
-ing成原始文件会更安全。
无法执行您想要的操作sed
。甚至sed
支持该-i
选项的版本也可以执行您明确声明的不想要的操作:它们写入一个临时文件,然后重命名该文件。但是也许您可以使用ed
。例如,改变所有出现foo
到bar
文件中file.txt
,你可以这样做:
echo ',s/foo/bar/g; w' | tr \; '\012' | ed -s file.txt
语法类似于sed
,但肯定不完全相同。
但是也许您应该考虑为什么不想使用重命名的临时文件。即使没有-i
支持sed
,也可以轻松编写脚本来为您完成工作。相反sed -i 's/foo/bar/g' file
,您可以这样做inline file sed 's/foo/bar/g'
。这样的脚本编写起来很简单。例如:
#!/bin/sh -e
IN=$1
shift
trap 'rm -f $tmp' 0
tmp=$( mktemp )
<$IN "$@" >$tmp && cat $tmp > $IN # preserve hard links
应该适合大多数用途。
inline
如上所述调用它并调用它:inline inputfile sed 's/foo/bar/g'
ed
只有真正可以就地回答。我第一次需要ed
。谢谢。一个小的优化是使用echo -e ",s/foo/bar/g\012 w"
或echo $',s/foo/bar/g\012 w'
shell允许它避免额外的tr
调用。
ed
并没有真正就地进行修改。从strace
输出中,GNU ed
创建一个临时文件,将更改写入该临时文件,然后重写整个原始文件,并保留硬链接。从truss
输出来看,Solaris 11 ed
还使用了一个临时文件,但是在使用w
命令进行保存后,将其重命名为原始文件名,这会破坏所有硬链接。
ed
附带当前的MacOS(莫哈韦,不管这营销术语手段)仍保留硬链接。YMMV
sed支持就地编辑。来自man sed
:
-i[SUFFIX], --in-place[=SUFFIX]
edit files in place (makes backup if extension supplied)
范例:
假设您有一个hello.txt
包含文本的文件:
hello world!
如果要保留旧文件的备份,请使用:
sed -i.bak 's/hello/bonjour' hello.txt
您将得到两个文件:hello.txt
内容:
bonjour world!
并hello.txt.bak
保留了旧内容。
如果您不想保留副本,则不要传递扩展参数。
您还可以使用重定向操作符<>
打开文件进行读写:
sed 's/foo/bar/g' file 1<> file
现场观看:
$ cat file
hello
i am here # see "here"
$ sed 's/here/away/' file 1<> file # Run the `sed` command
$ cat file
hello
i am away # this line is changed now
重定向运算符
[n]<>word
导致打开名称为单词扩展的文件,以便在文件描述符n或未指定n的文件描述符0上进行读写操作。如果该文件不存在,则会创建它。
就像Moneypenny在Skyfall中说的那样:“有时候旧的方法是最好的。” Kincade稍后也说了类似的话。
$ printf ',s/false/true/g\nw\n' | ed {YourFileHere}
编辑愉快。添加了“ \ nw \ n”来写入文件。很抱歉延迟回答要求。
|
。@MattMontag
\n
。[range] s / <old> / <new> / <flag>是替代命令的形式-在许多其他文本编辑器中仍然可以看到的范例(好的,vim,ed的直接后代)无论如何,g
标志代表“全局”,表示“您查看的每一行上的每个实例”。范围3,5
看第3-5行。,5
查看StartOfFile-5,3,
查看第3-EndOfFile行,然后,
查看StartOfFile-EndOfFile。每行上的全局替换命令,将“ false”替换为“ true”。然后,输入写命令w
。
-i
是gnu sed中的选项,但不是标准sed中的选项。但是,它将内容流式传输到新文件,然后重命名该文件,因此它不是您想要的。