代码之家  ›  专栏  ›  技术社区  ›  Ethan

如何在Vim中的目录中递归搜索和替换?

  •  37
  • Ethan  · 技术社区  · 14 年前

    我发现维姆的替代命令。。。

    :%s/replaceme/replacement/gi
    

    还有维姆格雷普。。。

    :vimgrep  /findme/gj  project/**/*.rb
    

    有没有一种方法可以将它们组合起来,以便在一个目录下的所有文件中进行替换?

    6 回复  |  直到 12 年前
        1
  •  74
  •   Laurence Gonsalves    6 年前

    尽管我是Vim用户,但我通常使用 find sed 为了这类事情。的正则表达式语法 塞德 与Vim的类似(他们都是 ed ),虽然不完全相同。使用GNU sed,您还可以使用 -i 用于就地编辑(通常为 塞德 将修改后的版本发送到stdout)。

    find project -name '*.rb' -type f -exec sed -i -e 's/regex/replacement/g' -- {} +
    

    逐件:

    • project
    • -name '*.rb' =用于名称与'*.rb'匹配的对象
    • -type f =和是常规文件(不是目录、管道、符号链接等)
    • -exec sed =运行 塞德
      • -e 's/regex/replacement/g' =执行“替换”命令(与Vim的命令几乎相同 :s ,但请注意缺少 % --这是默认的 塞德
      • -- =标志结束,文件名从这里开始
      • {} 这说明 找到 它找到的文件名应该放在sed的命令行中
      • + 这说明 -exec 操作已完成,我们希望将参数分组为尽可能少的参数 塞德 调用(通常比每个文件名运行一次更有效)。要对每个文件名运行一次,可以使用 \;

    这是GNU的一般解决方案 塞德 找到 . 在特殊情况下,这可以缩短一点。例如,如果您知道您的名称模式与您可以省略的任何目录都不匹配 -f型 - 你可以省略 -- . Here's an answer I posted to another question with more details on passing filenames found with find to other commands.

        2
  •  69
  •   Jonas G. Drange    12 年前

    args argdo 你应该做你需要的事。

    :args spec/javascripts/**/*.* 
    :argdo %s/foo/bar/g
    

    看见 this page .

        3
  •  8
  •   Dave Kirby    14 年前

    :set autowrite                  #automatically save the file when we change buffers
    :vimgrep /pattern/ ./**/files  
    qa                              #start recording macro in register a
    :s/pattern/replace/g            #replace on the current line
    :cnext                          #go to next matching line
    q                               #stop recording
    10000@a                          #repeat the macro 10000 times, or until stopped by 
                                    #an "error" such as reaching the end of the list
    :set noautowrite
    

    我还没有测试它,所以它可能需要一些调整-在一些文件上测试它,你不介意先弄乱它。

    编辑 :

        4
  •  7
  •   proton1    5 年前

    要回答结合vimgrep和substitute的原始问题,请执行以下操作:

    :vimgrep /pattern/ ./**/files              # results go to quickfix list
    :set autowrite                             # auto-save when changing buffers
    :silent! cdo %s/replaceme/replacement/gic  # cdo draws filenames from quickfix list
    :set noautowrite
    

    省去 c 属于 gic 如果您不想确认每次更换(在这种情况下,您也可以使用 find sed 正如@LaurenceGonsalves)所建议的那样。

        5
  •  6
  •   hgmnz    14 年前

    一种方法是打开所有要在其上运行替换的文件(或任何命令),然后运行 :bufdo <cmd> ,将运行 <cmd> 在所有打开的缓冲区上。

        6
  •  4
  •   Michał Marczyk    14 年前

    Vimgrep Replace .

    Global Replace , EasyGrep .

    argdo 如果你能帮我 vimgrep args

    第一个插件背后的基本思想(我猜其他插件也是…)是使用 首先,然后使用循环遍历匹配 :cnext 并在每行上应用替换命令。完成此任务的函数可能足够小,可以将其放入.vimrc中(也许你可以从插件的源代码中提取一个?)

    (我想hgimenez可能会找到一个解决方案,但它是否合适可能取决于要处理的文件数量。。。不管怎样,插件都应该是正常的。)

        7
  •  0
  •   rado    10 年前

    维姆找到了-f型`

    :bufdo%s/图案/替换/gec |更新