如何将当前目录下出现的每个字符串替换为另一个字符串?
示例: 我想将当前目录下每个文件中出现的所有
www.fubar.com
替换为 www.fubar.ftw.com
。
根据迄今为止的研究,我得出了
sed -i 's/www.fubar.com/www.fubar.ftw.com/g' *.php
您的方向是正确的,请使用
find
找到文件,然后使用 sed
编辑它们,例如:
find . -name '*.php' -exec sed -i -e 's/www.fubar.com/www.fubar.ftw.com/g' {} \;
注释
.
表示当前目录 - 即在本例中,在当前目录及其下搜索。sed
,您需要为-i
选项指定扩展名,该选项用于备份文件。-exec
选项后面是要应用于找到的文件的命令,并以分号终止,分号必须转义,否则 shell 在传递给 find 之前将其消耗掉。比当前接受的解决方案更高效的*替代方案:
grep "www.fubar.com" . -lr | xargs sed -i 's/www.fubar.com/www.fubar.ftw.com/g'
这避免了
find . -exec
方法的低效率,该方法不必要地对当前目录下的所有文件运行 sed
就地替换,无论它们是否包含您要查找的字符串,而是使用 grep -lr
。这仅获取包含要替换的字符串的文件,然后您可以通过管道传输到 xargs sed -i
以仅对这些文件执行就地替换。
* :我使用
time
对我的方法与已接受的解决方案进行了粗略比较(适合我自己的用例); find . -exec
风格的方法在我的机器上运行需要 3.624s,而我上面提出的解决方案需要 0.156s,所以对于我的用例来说大约快了 23 倍。
使用 find、args 和 sed 的解决方案:
find . -name '*.php' -print0 | xargs -0 sed -i 's/www.fubar.com/www.fubar.ftw.com/g'
一个纯粹的 bash 解决方案
#!/bin/bash
shopt -s nullglob
for file in *.php
do
while read -r line
do
echo "${line/www.fubar.com/www.fubar.ftw.com}"
done < "$file" > tempo && mv tempo "$file"
done
当使用 ZSH 作为你的 shell 时,你可以这样做:
sed -i 's/www.fubar.com/www.fubar.ftw.com/g' **/*.php
如果没有子文件夹,更容易记住的方法是
replace "www.fubar.com" "www.fubar.ftw.com" -- *
其中 * 也可以是文件列表 你需要这个别名才能像这样简单地工作:
alias replace='function _replace() { from="$1"; to="$2"; shift 2; find . -type f \( -name "$@" \) -exec sed -i "s/${from}/${to}/g" {} +; }; _replace'
如果您有带点的隐藏文件,您可以使用
将它们添加到
*
shopt -s dotglob
如果您只有 一个深度的子文件夹,您可以使用
*/*
而不是 *
replace "www.fubar.com" "www.fubar.ftw.com" -- */*