【问题标题】:Simplest way to properly search and replace source code正确搜索和替换源代码的最简单方法
【发布时间】:2012-01-26 13:31:40
【问题描述】:

每次出现这种情况(大约每几个月一次)时,我最终都会花费太长时间试图找出一个 bash 脚本来完全满足我的需求。我很确定我想要的与其他人想要的相似,但是当我进行快速搜索时,在线可用的脚本往往过于简单并且不做这些事情(而且我自己的 bash 脚本编写技能也不好足以弄清楚):

  1. 需要递归(遍历整个文件夹树)
  2. 它必须允许我选择文件类型(例如“*.js”),因为有时文件夹树包含不应搜索的二进制文件和其他文件类型
  3. 它应该就地替换文本,编辑现有文件
  4. 它不应该导致源代码控制(git、svn)认为文件已被修改,除非它实际上已被修改(我不知道为什么,但 sed 似乎这样做)
  5. 应该允许正则表达式

最简单的方法是什么?我的意思是,我可以用python写一个脚本,只有几行,但我觉得这在shell中应该很容易完成。

【问题讨论】:

    标签: bash shell search replace sed


    【解决方案1】:

    我通常会这样做:

    find . -name '*.hpp' -o -name '*.cpp' | xargs grep -l StuffToEdit
    

    然后我看看我是否收到了感兴趣的文件。如果是,我添加到管道中:

    | xargs sed -i 's@StuffToEdit@NewStuffInstead@g'
    

    让我们撕开吧。

    如果 sed 让您的 VCS 认为文件没有更改,您应该查看差异。也许您在差异中关闭了空格,但这就是正在发生变化的内容(行尾等)?

    我相信有人会指出我对 xargs 的一种或两种用法没有必要,但对于一次性工作来说,这并不重要。无论如何,对于这类任务,我更喜欢这些多程序管道,因为我可以轻松禁用或换出某些过滤器,如果一开始结果不正确,我可以检查其余的结果。

    【讨论】:

    • find 的 -exec 会比 xargs 更安全也更快,请参阅下面的其他解决方案
    • 在这个特定的上下文中更安全和更快可能无关紧要(至少对于健全的代码库)。我在回答中解释了为什么 xargs 虽然更糟,但在这种情况下会更好——在不记住太多的情况下更容易正确处理,如果解决方案不能按照您需要的方式工作,则更容易分解解决方案。 OP要求最简单的方法,人们通常会忘记神秘的 {} \; find -exec 所需的废话。
    • 好吧,除非你开始使用它,否则你永远不会记得它:)
    【解决方案2】:

    这应该根据您的要求工作:

    find /path/to/dir/ -type f -name "*.txt" -exec sed -i 's/substitution/replacement/g' {} \;
    |                 | |                     |    |                                   |     
     -----------------   ---------------------      -----------------------------------   
             |                     |                                 |                      
    This will do the     This will allow you        This will do your substitution. -i       
    search of files      to specify filename        option will do it inline. You can     
    recursively for      You can also use           use -r option to use Extended Regex  
    the supplied path.   -regex option for          as sed's native support is BRE.       
                          better search. -type
                         is to limit your search. 
                         i.e f for regular files,
                         d for directories, l for 
                         symbolic links etc
    

    【讨论】:

      【解决方案3】:
      find /path/to/source/tree -name \*.js -exec sed -i -e'edit stuff here' {} \;
      

      【讨论】:

      • find /path/to/source/tree -not -path '**/.??*/**' -name \*.js -exec sed -e 's/foo/bar/g' {} \; 也许,也可以省略 Subversion 和其他控制文件。
      【解决方案4】:
      find . -name "*.cpp" -o -name "*.hpp"|xargs perl -pi -e 's/search/replace/g'
      

      【讨论】:

        【解决方案5】:

        嗯,你可以通过下面的脚本来制作它。

        find . -name "*.js" | grep -v "\.svn" |xargs sed -i -e "s/src/dst/g"
        
        1. cd 你的项目目录
        2. 找到您的目标文件类型
        3. 过滤掉svn
        4. 将每个文件放入 sed 命令。
        5. 在上面的 sed 脚本中,“src”和“dst”支持 regx。

        希望对你有帮助:)

        【讨论】:

          【解决方案6】:

          您可以使用ex 命令(Vim 的一部分,与vim -E 相同),例如

          ex "+bufdo! %s/foo/bar/g" -scxa **/*.js
          

          如果你的 shell 支持a new globbing option(启用:shopt -s globstar),** 将递归工作。

          解释:

          • bufdo! - 为参数中的所有文件强制调用下一个命令;
          • %s/foo/bar/g - sfoo 替换为bar g局部(% - 整个文件,g - 多个实例);
          • -scxa - s悄悄执行cute保存并退出(x)all;

          sed相比,使用ex具有以下优势:

          • sedStream EDitor,而不是文件编辑器。 BashFAQ/021
          • 它不会像sed is doing this by default那样破坏符号链接。
          • Ex 语法更高级(因为它使用 Vim 命令)并且更可靠(例如,sed 中的 -i 是非标准 FreeBSD 扩展,可能无法在其他操作系统上使用)。

          【讨论】:

            【解决方案7】:

            如果您正在处理 git 存储库,此脚本可让您搜索替换 perl 正则表达式模式:https://github.com/Chiel92/replac

            USAGE: replace <FIND_PATTERN> <SUBSTITUTE_PATTERN> [<ARBITRARY GIT GREP PARAMETERS>] [--now]
            
            The patterns are treated as Perl regex patterns and the other arguments
            are treated like the corresponding grep arguments.
            If the "now" flag is not given, replace will run in dry mode
            
            EXAMPLE:
            replace "number:(\d)" "digit:$1" ../libs -- \*.{cpp,h} --now
            

            【讨论】:

              猜你喜欢
              • 2012-09-14
              • 2016-04-27
              • 1970-01-01
              • 1970-01-01
              • 2010-11-23
              • 1970-01-01
              • 2011-12-19
              • 1970-01-01
              • 2021-03-03
              相关资源
              最近更新 更多