如何查找不同行中包含两个字符串的文件

如何查找不同行中包含两个字符串的文件

一个真实的例子是:我有一个Python文件util.py,我将其中一个函数名称从更改foobar。可能还有其他文件用作foo函数名称,并且它们是不相关的。

我想将项目中的所有 Python 文件从 更新foobar.所以我想搜索导入的文件,例如:

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要求

  1. 递归搜索 ( -r)
  2. 输出匹配文件的名称 ( -l)
  3. 用 NUL 而不是 LF ( -Z)分隔
  4. 只考虑以 '.py' 结尾的文件 ( --include='*.py')

并要求在所有匹配文件中sed执行就地替换(-i)(如果有的话xargs -r)。

答案2

这应该可以。

/gfoo将替换所有实例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

相关内容