Bash 正确搜索和替换源代码的最简单方法

Bash 正确搜索和替换源代码的最简单方法,bash,shell,search,replace,sed,Bash,Shell,Search,Replace,Sed,每当这种情况出现时,也就是大约每隔几个月出现一次,我都会花太长时间试图找出一个能完全满足我需求的bash脚本。我非常确定我想要的与其他人想要的相似,但通常情况下,当我进行快速搜索时,在线可用的脚本过于简单,并且不做这些事情(我自己的bash脚本技能还不足以解决这个问题): 它需要递归(遍历整个文件夹树) 它必须允许我选择文件类型(例如“*.js”),因为有时文件夹树包含二进制文件和其他不应搜索的文件类型 它应该替换文本,编辑现有文件 它不应该让源代码管理(git、svn)认为文件已经被修改,除非

每当这种情况出现时,也就是大约每隔几个月出现一次,我都会花太长时间试图找出一个能完全满足我需求的bash脚本。我非常确定我想要的与其他人想要的相似,但通常情况下,当我进行快速搜索时,在线可用的脚本过于简单,并且不做这些事情(我自己的bash脚本技能还不足以解决这个问题):

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

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

    我通常会这样做:

    find /path/to/source/tree -name \*.js -exec sed -i -e'edit stuff here' {} \;
    
    find . -name '*.hpp' -o -name '*.cpp' | xargs grep -l StuffToEdit
    
    然后我看看我是否得到了感兴趣的文件。如果是,我将添加到管道中:

    | xargs sed -i 's@StuffToEdit@NewStuffInstead@g'
    
    让我们撕开

    如果sed让你的风投认为文件被更改了,而他们没有更改,那么你应该看看差异。也许您在差异中关闭了空白,但这就是变化的原因(行尾或类似的情况)


    我相信有人会来指出,我在上面使用xargs的一个或两个方法是没有必要的,但对于一次性工作来说,这并不重要。无论如何,我更喜欢这些多程序管道来完成这类任务,因为我可以很容易地禁用或调出某些过滤器,并检查其他过滤器的结果(如果最初的结果不正确)。

    好的,您可以通过下面的脚本来完成

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

  • 希望这将对您有所帮助:)

    这将符合您的要求:

    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
    

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

    如果您的shell支持(通过以下方式启用:
    shopt-s globstar
    ),则
    **
    将递归工作

    说明:

    • bufdo-对参数中的所有文件强制调用next命令
      
    • %s/foo/bar/g
      -s
      foo
      替换为
      bar
      g全局(
      %
      -整个文件,
      g
      -多个实例)
    • -scxa
      -silely execute保存并退出(x)all
    使用
    ex
    比使用
    sed
    具有以下优点:

    • sed
      是一个StreamED编辑器,而不是文件编辑器
    • 它不会像以前那样破坏符号链接
    • Ex语法更高级(因为它使用Vim命令),而且更可靠(例如
      sed
      中的
      -i
      是非标准的FreeBSD扩展,在其他操作系统上可能不可用)

    如果您处理的是git存储库,此脚本允许您搜索替换perl正则表达式模式:

    用法:替换[][--now]
    这些模式被视为Perl正则表达式模式和其他参数
    与相应的grep参数一样处理。
    如果未给出“now”标志,则replace将在干燥模式下运行
    例子:
    将“数字:(\d)”替换为“数字:$1”。/libs--\*.{cpp,h}--now
    
    find/path/to/source/tree-not-path'**/.??*/**'-name\*.js-exec sed-e's/foo/bar/g'{}也许,也可以省略Subversion和其他控制文件。find的-exec将比xargs更安全、更快,请参阅下面的其他解决方案。在这种特定的上下文中,安全和更快可能与此无关(至少对于健全的代码库)。我在回答中解释了为什么xargs在这种情况下更好,虽然更糟糕,但它更容易准确无需记住太多内容,而且如果解决方案不能按您需要的方式工作,则更容易分解。OP要求最简单的方法,人们通常会忘记神秘的{};find-exec需要的废话。好吧,除非你开始使用它,否则你永远不会记得它:)
    
    find . -name "*.cpp" -o -name "*.hpp"|xargs perl -pi -e 's/search/replace/g'
    
    ex "+bufdo! %s/foo/bar/g" -scxa **/*.js
    
    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