基于正则表达式的递归查找和替换

时间:2012-06-03 01:48:38

标签: regex linux unix grep

我改变了我的导演结构,我想做以下事情:

  • 执行递归grep以查找匹配的所有实例
  • 更改为更新的位置字符串

一个例子(数百个)将是:

from common.utils import debug  --> from etc.common.utils import debug

获取我正在寻找的所有实例:

$ grep -r 'common.' ./

但是,我还需要确保common前面有空格。我该怎么做才能找到并替换?

3 个答案:

答案 0 :(得分:4)

很难准确说出你想要什么,因为你的重构示例改变了导入和包,但是以下内容将改变目录中所有文件的common. -> etc.common.

sed -i 's/\bcommon\./etc.&/' $(egrep -lr '\bcommon\.' .)

这假设你有可用的gnu sed,这是大多数linux系统所做的。另外,只是为了让您知道,如果sed一次处理的文件太多,这将失败。在这种情况下,您可以这样做:

egrep -lr '\bcommon\.' . | xargs sed -i 's/\bcommon\./etc.&/'

请注意,以sed -i'.OLD' 's/\bcommon\./etc.&/'运行sed命令可能是个好主意,这样您就可以获得原始文件的备份。

答案 1 :(得分:1)

这大致是你如何使用find来做到这一点。这需要测试

 find . -name \*.java -exec sed "s/FIND_STR/REPLACE_STR/g" {}

这转换为“从当前目录开始查找以.java结尾并在文件上执行sed的所有文件(其中{}是当前找到的文件的占位符)”s / FIND_STR / REPLACE_STR / g“替换在当前文件的每一行中使用REPLACE_STR的FIND_STR。

答案 2 :(得分:1)

如果您的grep实现支持Perl语法(-P标记,例如Linux通常可用),您可以从字边界等附加功能中受益:

$ grep -Pr '\bcommon\.'

顺便说一下:

grep -r往往比之前的管道find命令要慢得多,就像在Rob的例子中那样。此外,当您确定找到的文件名不包含任何空格时,使用xargs要比-exec快得多:

$ find . -type f -name '*.java' | xargs grep -P '\bcommon\.'

或者,适用于蒂姆的例子:

$ find . -type f -name '*.java' | xargs sed -i.bak 's/\<common\./etc.common./'

请注意,在后一个示例中,替换是在为每个更改的文件创建* .bak备份之后完成的。这样,您可以查看命令的结果,然后删除备份:

$ find . -type f -name '*.bak' | xargs rm

如果您制作了一个oopsie,则以下命令将恢复以前的版本:

$ find . -type f -name '*.bak' | while read LINE; do mv -f $LINE `basename $LINE`; done

当然,如果您不确定文件名和路径中是否有空格,则应通过find的{​​{1}}参数应用命令。

干杯!