是否可以像这样用 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 ...
将打印提供find
给sed
.
有关的:
答案2
您的 sed 会话适用于 grep 的输出,而不是实际文件。
用于grep
列出文件 (*)
grep -e "http://localhost:4000" -r ~/dev_web/_site -l
然后使用xargs
和sed -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 从文件中提取行,而不是列表文件。
要获取匹配的文件列表,请使用-l
grep 选项:
$ 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 操作。
问候