一个真实的例子是:我有一个Python文件util.py
,我将其中一个函数名称从更改foo
为bar
。可能还有其他文件用作foo
函数名称,并且它们是不相关的。
我想将项目中的所有 Python 文件从 更新foo
为bar
.所以我想搜索导入的文件,例如:
import project.path.util
或者
from project.path.util import foo
以及任何以foo
以下开头的调用:
foo(
该解决方案必须能够容忍空格。我可以使用它们中的每一个进行搜索grep
,但我不确定组合搜索。任何建议将不胜感激。
答案1
使用 GNU 工具:
grep -rlZ --include='*.py' -e 'import project.path.util' \
-e 'from project.path.util import.*\bfoo\b' . |
xargs -r0 sed -i 's/\bfoo\b/bar/g'
这是通过grep
要求
- 递归搜索 (
-r
) - 输出匹配文件的名称 (
-l
) - 用 NUL 而不是 LF (
-Z
)分隔 - 只考虑以 '.py' 结尾的文件 (
--include='*.py'
)
并要求在所有匹配文件中sed
执行就地替换(-i
)(如果有的话xargs -r
)。
答案2
这应该可以。
/g
foo
将替换所有实例bar
find <Project root dir> -type f -exec sed -i "{}" -e 's/foo/bar/g' \;
如果您想限制仅对 *.py 文件进行更改:
find <Project root dir> -type f -name "*.py" -exec sed -i "{}" -e 's/foo/bar/g' \;
如果有 foo 实例不应被替换,则可以限制为 4 种情况:
- 进口富
- 从模块导入富
- 定义富
- 富(
但不是
- 该死的_foo(
- 该死的富(
- 该死的1foo(
- 该死的富(
那么命令将如下所示:
foo="foo";bar="bar";find <Project root dir> -type f -exec sed -i "{}" \
-r -e "s/[^a-zA-Z0-9_\-]$foo\(/$bar\(/g" -e "s/def $foo/def $bar/g" \
-e "s/import $foo/import $bar/g" \;
答案3
假设您位于想要搜索的目录中(它也与任何子目录匹配):
for i in `find . -type f -name '*.py' -exec grep -lr 'foo' {} +`; do sed -i 's/foo/bar/' $i; done
编辑:
为了避免匹配包含字符的函数,例如“damned_fools”,我们可以使用 \b 来改进它以匹配单词边界:
for i in `find . -type f -name '*.py' -exec grep -lr 'foo' {} +`; do sed -i 's/\bfoo\b/bar/' $i; done
参考: https://stackoverflow.com/questions/1032023/sed-whole-word-search-and-replace