【问题标题】:Recursive find and replace based on regex基于正则表达式的递归查找和替换
【发布时间】:2012-06-03 01:48:37
【问题描述】:

我已经改变了我的主管结构,我想做以下事情:

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

一个例子(数百个)是:

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

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

$ grep -r 'common.' ./

但是,我还需要确保common 前面有一个空格。我将如何进行查找和替换?

【问题讨论】:

  • egrep 是一个 Solaris 命令 afaikr。
  • @RobKielty egrep 至少在所有 gnu 系统上,是 grep -E 的缩写(扩展的正则表达式,这里实际上不需要)
  • 另外,OP,你想要\.,而不仅仅是.;否则它被解释为除了换行符之外的任何东西。
  • OP 你能准确说出你想要做的改变吗?必须根据您需要完成的操作找出 a sed 命令。
  • 其实egrep 可以追溯到贝尔实验室最初的 Unix。

标签: regex linux unix grep


【解决方案1】:

很难准确说出您想要什么,因为您的重构示例会更改导入以及包,但以下内容将更改目录中所有文件的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 命令可能是个好主意,这样您就可以获得原始文件的备份。

【讨论】:

    【解决方案2】:

    如果您的 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-exec 参数应用命令。

    干杯!

    【讨论】:

    • 对于简单的单词边界,您不需要-P,但在egrep 中它们是左侧的\&lt; 和右侧的\&gt;
    • 谢谢。这就是我在阅读蒂姆的帖子后得出的结论。我立即在我的vi 中尝试了它。当然,它奏效了。然后我问自己这些年我做了什么。现在我不知道我应该为这个新功能感到高兴还是为所有浪费的时间哭泣......
    • @tripleee egrep 还支持\b 用于单词边界。 \&lt;\&gt; 只是 \b 的边缘特定版本。
    【解决方案3】:

    这就是您使用 find 的大致方法。这需要测试

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

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

    【讨论】:

    • 来自 vi 的习惯力量。我删除了它。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-03-25
    • 2011-06-16
    • 1970-01-01
    • 2017-01-28
    • 2015-01-11
    • 2012-12-02
    相关资源
    最近更新 更多