我的命令大致如下:
sed -e s/STRING_TO_REPLACE/STRING_TO_REPLACE_IT/g index.html > index.html
当我运行这个程序并查看文件后,发现它是空的。它删除了我的文件内容。
在我再次恢复文件后运行此程序:
sed -e s/STRING_TO_REPLACE/STRING_TO_REPLACE_IT/g index.html
stdout
是文件内容,查找和替换已经执行。
为什么会发生这种情况?
sed -e s/STRING_TO_REPLACE/STRING_TO_REPLACE_IT/g index.html > index.html
当我运行这个程序并查看文件后,发现它是空的。它删除了我的文件内容。
在我再次恢复文件后运行此程序:
sed -e s/STRING_TO_REPLACE/STRING_TO_REPLACE_IT/g index.html
stdout
是文件内容,查找和替换已经执行。
为什么会发生这种情况?
> index.html
时,它将打开index.html
文件以进行写入操作,并擦除其先前的所有内容。sed
传递-i
选项,使更改内联,并在进行原地更改之前创建原始文件的备份:sed -i.bak s/STRING_TO_REPLACE/STRING_TO_REPLACE_IT/g index.html
没有 .bak 扩展名,这个命令在某些平台上会失败,例如 Mac OSX。
sed -i '' 's/blah/xx/g'
。 - Pierre Houstonsed -i
后面的 .bak
是什么意思?(注:.bak 是备份文件的后缀名) - Patrizio Bertoni另一种有用的模式是:
sed -e 'script script' index.html > index.html.tmp && mv index.html.tmp index.html
这样做的效果基本相同,无需使用 -i
选项,而且意味着如果 sed 脚本由于某种原因失败,输入文件不会被覆盖。此外,如果编辑成功,就没有备份文件留下来。在 Makefiles 中这种惯用语法很有用。
相当多的 sed 命令有 -i
选项,但并非所有的都有;其中 posix sed 就没有。因此,如果你希望实现可移植性,最好避免使用。
... && mv index.html{.tmp,}
- EdwardGsh
不支持 {...}
的扩展。在Makefile中你可能会使用sh
而不是bash
,所以如果你想要可移植性(或符合posix标准),那么你需要避免使用那种语法结构。 - Norman Graymv index.html $(echo index.html | sed -e 'script')
- Timosed -i 's/STRING_TO_REPLACE/STRING_TO_REPLACE_IT/g' index.html
这会在文件index.html上进行全局就地替换。引用字符串可以防止查询和替换中的空格问题。
使用sed的-i选项,例如:
sed -i bak -e s/STRING_TO_REPLACE/REPLACE_WITH/g index.html
's/需要替换的字符串/替换成的字符串/g'
- Doug Thompson-i
用于对文件进行原地编辑,因此将其与标准输入结合使用是没有意义的。 - mklement0要更改多个文件(并将每个文件另存为*.bak的备份):
perl -p -i -e "s/\|/x/g" *
将目录中的所有文件,并将|
替换为x
。这被称为“Perl饼干”(如同吃馅饼一样简单)
sed
指定为要求,只是将其作为已经尝试过的工具使用。 - Chindraba你应该尝试使用选项-i
进行原地编辑。
sed
的-i
选项外,您还可以使用tee
实用程序。man
中得知:
因此,解决方案如下:tee-从标准输入读取并写入标准输出和文件
sed s/STRING_TO_REPLACE/STRING_TO_REPLACE_IT/g index.html | tee | tee index.html
tee
被重复使用以确保管道被缓冲。然后,在管道中的所有命令都被阻塞,直到它们获得一些可用的输入。在管道中的每个命令在上游命令写入 1 个缓冲区字节(大小在某些地方被定义)到命令的输入之后开始。因此,最后一个命令tee index.html
,打开文件以进行写操作并因此将其清空,在上游管道完成且输出位于管道内缓冲区之后运行。sed s/STRING_TO_REPLACE/STRING_TO_REPLACE_IT/g index.html | tee index.html
-- 它会同时运行管道的两个命令,而不会有任何阻塞。(不阻塞时,管道应逐行传递字节,而不是逐缓冲区传递。与运行cat | sed s/bar/GGG/
时相同。没有阻塞,它更加交互式,并且通常只有2个命令的管道运行时没有缓冲和阻塞。更长的管道会被缓冲。)tee index.html
将打开文件进行写入,并将其清空。但是,如果您始终打开缓冲,则第二个版本也可以正常工作。
sed -i.bak "s#https.*\.com#$pub_url#g" MyHTMLFile.html
$pub_url
。这里的s
表示搜索,g
表示全局替换。命令存在的问题
sed 'code' file > file
这是因为在sed实际处理文件之前,shell会截断file
文件。结果就是你得到了一个空文件。
解决这个问题的sed方法是使用-i
选项进行原地编辑,正如其他答案所建议的那样。然而,这并不总是你想要的。 -i
将创建一个临时文件,然后用它来替换原始文件。如果原始文件是链接,则会出现问题(链接将被替换为常规文件)。如果您需要保留链接,可以使用临时变量存储sed的输出,然后将其写回文件,像这样:
tmp=$(sed 'code' file); echo -n "$tmp" > file
printf
而不是echo
,因为在某些shell(例如dash)中,echo
很可能会将\\
处理为\
。tmp=$(sed 'code' file); printf "%s" "$tmp" > file
sed 'code' file > file.tmp; cat file.tmp > file; rm file.tmp
- dashohoxha而且 ed
的答案是:
printf "%s\n" '1,$s/STRING_TO_REPLACE/STRING_TO_REPLACE_IT/g' w q | ed index.html
重申一下codaddict的答案,shell先处理重定向操作,清空了"input.html"文件,然后再调用"sed"命令并传递一个现在为空的文件。
sed
的ed
版本”的答案?它执行得更快吗? - cregoxsed
命令不支持使用-i
选项来原地编辑文件。而ed
则非常普遍,并且可以让你将修改后的结果保存到原文件中。此外,拥有多种工具也总是有益的。 - glenn jackmanprintf "%s\n" '1,$s/^STRING_TO_REPLACE.*/$MODPATH/g' w q | ed $SERVICESH > /dev/null 2>&1
。我想将$MODPATH作为替换字符串传递,但无法使其正常工作。 - Some53
perl -pi -w -e 's/STRING_TO_REPLACE/REPLACE_WITH/g;' index.html
(将index.html
文件中的所有STRING_TO_REPLACE
替换为REPLACE_WITH
,并且会直接修改原文件) - Gjorgji Tashkovskised
命令查找字符串并替换整行的相关内容,请参考以下链接:https://dev59.com/82gu5IYBdhLWcg3wj3r5 - cregox