在Windows下使用vim grep的正確姿勢

weixin_34308389發表於2016-08-02

[TOC]

首先, 開發環境是Windows,
然後, 我又是一個信仰堅定的Vimer,
所以就出現了Windows + Gvim這個有些不太協調的組合, 想在蓋茨叔叔的視窗OS上稍微正常的使用Gvim還是有些小麻煩, 可是這都難不倒一個有信仰的Vimer.

PS 如果你使用Osx or Linux, 大可不必這樣折騰, 直接使用ack.vimgrep.vim吧, 簡單的配置就可以搞定.

在Win上使用grep的可選方案

在Windows上使用grep搜尋文字有以下幾種方案:

  1. 使用grep命令, 雖是GNU下的工具, 但也有Win移植版;
  2. 使用vim內建的vimgrep命令, 速度最慢但是相容性相對好;
  3. 使用Win下的原生命令findstr;
  4. 使用Win移植版的ack, 這種方法我沒嘗試過, 如果你用過了, 請一定告訴我:P

使用grep

雖然grep.vim外掛也可以在Windows上使用, 外掛也提供了一些Win下使用的選項, 但grep.vim這款外掛呼叫的是grep命令, Win上沒有grep, 怎麼辦?
後來找到了grep在Win平臺的移植版: GnuWin
相關設定選項參考這裡: grep.vim : Grep search tools integration with Vim , 在頁面上搜尋"MS-Windows"就可以看到for Windows的特殊選項.
不過,移植版的grep也有很多相容問題, 略過不表233
什麼, 你問我為什麼不早說, 因為我一寫部落格就容易囉嗦...
好吧. 接下來說另一種使用vimgrep的方案:

使用vimgrep

之前有過一篇介紹: vim中的殺手級外掛: EasyGrep,
EasyGrep使用的是vim內建的搜尋命令vimgrep, 相比上面說的移植版grep, vimgrep 在Win上相容性要大大好於上面的grep移植版.
不過EasyGrep提供了一個比較友好的搜尋選項介面, 就像下面這個樣子, 調整搜尋選項是不是要比grep.vim直觀許多?

EasyGrep Options

vimgrep的最大問題是搜尋效率, 真的很差, 尤其你要搜尋的目錄裡有成百上千的檔案時.
這時候可以切到Chrome裡刷一會知乎...
但刷完知乎後卻發現vimgrep仍舊在努力的轉動你的硬碟... 所以我又放棄了EasyGrep.

使用findstr

Windows下提供了一個原生命令findstr, 相當於Linux下的grep.
如果你想了解一下findstr命令的使用姿勢, 可以看這裡: Findstr - TechNet - Microsoft
在vim.org上也找了一個為findstr寫的外掛 -- findstr.vim : Using MS-Windows findstr utility to search for text with Vim
看來在Windows上用Vim的可憐人兒還不少, 我覺得這款外掛的作者就是一個:(
不過這外掛簡直可算得上樸素, 只提供了四個外掛命令, 我覺得跟手動敲findstr命令列效率差不多, 可是我懶且健忘, 記不住這麼多findstr引數,
等等, 剛才聊到的EasyGrep的搜尋選項介面不是挺方便的嘛, 所以, 為什麼不能把EasyGrep的搜尋介面搬到findstr.vim上來?
恩, 對於程式設計師來說這並不難, vimscript似乎有些像shell和php的結合語言. 所以...

改進後的findstr.vim

靠著google和勤勉的copy, 一個帶有良好人機互動的多功能findstr.vim被提交到了github上(666)
Github repository在這裡: https://github.com/WhatsDJGPP/findstr.vim

findstr

在vimrc裡新增一行配置:

nmap <leader>gg :VimFindstr<CR>

這樣, 在普通模式按下\gg就可以愉快的使用findstr了.

參考

附: vimgrep命令

vimgrep命令格式如下:

vimgrep /搜尋字串/gj 檔案

上面的gj引數都是可選的,

  • /g : 加上g引數的話, 如果一行有多個匹配, 那麼這些匹配會都出現在搜尋結果裡, 所以一般不用加/g引數;
  • /j : 如果不加j引數, 執行完vimgrep會自動跳轉到第一個匹配處, 所以一般都會加上/j引數;

比如vimgrep /keyword/j *.php表示僅在當前目錄下的所有php檔案裡搜尋"keyword", 且不自動跳轉到搜尋結果.
如果也要在子目錄遞迴搜尋, **表示在當前目錄以及子目錄遞迴, 比如**/*.php

一些栗子:

  • 當前目錄下遞迴搜尋: vimgrep /字串/j **/*.php
  • 僅當前目錄, 不遞迴: vimgrep /字串/g *.php
  • 如果要搜尋多個副檔名, 用空格分開即可: vimgrep /字串/j **/*.cpp **/*.php
  • Linux絕對路徑, 遞迴搜尋: vimgrep /字串/j /home/user/**/*.cpp
  • Win絕對路徑, 遞迴搜尋: vimgrep /字串/j D:\home\user/**/*.cpp

補充

@2016-08-01 發現一個問題, findstr.vim試用的是system(cmd)來執行findstr命令, 正常情況下這是沒什麼問題的, 但當遇到中文目錄的時候, system執行的結果中的中文會變成"<3b><4a>"這樣的程式碼. 所以搜尋在中文目錄會很蛋疼, 在quickfix裡跳轉不到正確的檔案.
折中的辦法是, 外掛新增一個選項, 可以在使用findstr和vimgrep之間切換, 一般情況下推薦使用效率更高的findstr, 只有當遇到上面的問題時才使用"slowly but compatible"的vimgrep.

findstr迭代了幾個版本, 修改了一些bug和改進易用性, 歡迎fork, 提交pr和issue:)


講一個笑話, 從前森林裡有隻猴子, 為了能更方便的吃到櫻桃, 所以這隻猴子自己種了一棵櫻桃樹.

相關文章