递归地用 SED 替换

递归地用 SED 替换

是否可以像这样用 grep 和 sed 在多目录中递归地替换示例?

grep -e "http://localhost:4000" -r ~/dev_web/_site  | sed -e 's/http:\/\/localhost:4000/https:\/\/another_site.com/g'

当我这样做时,我的终端显示已完成,但是当我再次执行 grep 时:

grep -e "https://another_site.com" -r ~/dev_web/_site

它显示我只更改了 4 个文件..

如果我这样做:

 grep -e "http://localhost:4000" -r ~/dev_web/_site/

示例 http:localhost:4000 仍然在这里

答案1

您的管道没有更改任何文件。它使用 提取与正则表达式匹配的行grep,然后更改该数据,但不会尝试在任何文件中进行更改。

相反,假设 GNU sed

find ~/dev_web/_site -type f \
    -exec grep -qF 'http://localhost:4000' {} ';' \
    -exec sed -i 's#http://localhost:4000#https://another.site#g' {} +

这将查找目录 中或目录下的所有常规文件~/dev_web/_site。对于每个这样的文件,grep首先测试该文件是否包含给定的字符串。如果包含,则sed调用 GNU 进行就地替换。

grep步骤可以省略,但 GNUsed会更新修改时间戳全部没有它的文件。

您可能只想查看下面目录中的文件子集~/dev_web/_site。如果是这种情况,-name '*.js'请在 后使用类似的内容(或您想要匹配的任何名称模式)来限制搜索-type f

-print在之前添加-exec sed ...将打印提供findsed.

有关的:

答案2

您的 sed 会话适用于 grep 的输出,而不是实际文件。

用于grep列出文件 (*)

grep -e "http://localhost:4000" -r ~/dev_web/_site -l 

然后使用xargssed -i就地编辑

xargs sed -i -e 's;http://localhost:4000;https://another_site.com;g'

(顺便说一句,您可以更改 sed 中的分隔符)

现在大家在一起

grep -e "http://localhost:4000" -r ~/dev_web/_site -l |
xargs sed -i -e 's;http://localhost:4000;https://another_site.com;g'

当然,这可以是单行的,请注意管道符号 ( |) 可以使用续行。

(*) 我假设文件名称中没有空格、换行符和其他有趣的字符。

答案3

你的第一个 grep 从文件中提取行,而不是列表文件。
要获取匹配的文件列表,请使用-lgrep 选项:

$ grep -rl "htt...."  ~/dir

要使用 sed 执行文件修改,请将列表提供给 sed (反转顺序):

$ sed -e 's#http://localhost:4000#https://another_site.com#g' \
$(grep -rle "http://localhost:4000" ~/dev_web/_site)

假设“干净”的文件名:没有空格或新行。

更强大的选项是使用 find:

fromname='http://localhost:4000
toname='https://another_site.com'
searchdir=~/dev_web/_site
find "$searchdir" -type f \
    -exec grep -qF "$fromname" {} ';' \
    -exec sed -i 's#'"$fromname"'#'"$toname"'#g' {} +

答案4

对我来说最好的是使用 for :

for i in $(grep -R "string_to_change" | awk -F: '{print $1}');do sed -i 's/string_to_change/string_changed/g' $i ;done

解释:使用 grep -R 递归查找字符串,始终在名称前面加上 : ,这样您就可以获得文件的路径。最后对提取的文件执行 sed 操作。

问候

相关内容