Sponsored Link

WindowsでVimでpt

pt(Platinum Searcher) お世話になっております。

grepやagなどありあますが、なぜptかといえば、

なにせ早い、日本語系の文字コードが使える、これに尽きます。

似た仕様を満たしているものでhighwayというものもあるみたいですが、こちらはwindowsがサポートされてないようなので

ptです。

で、vimもそうなんですが、ptをはじめとするgrep系のコマンドも、Windowsでの使い方ってやっぱりUnix系と比べると特殊だったりこつがいる部分があったりするんですよね。

もともとのデが、Unix上での実装なので当然の成り行きではあるのですが、
わたくし、仕事がバリッバリのWindowsマンなので、Windowsでうまいこと使えないと困ってしまうわけです。

というわけでWindowsで、ptとvimを併用して使うときのちょっとした覚書です。

Sponsored Link

ptコマンドをWindows上で使う際の注意

まずはpt自体の使い方。通常の使い方はpt --helpしてもらうとして、

挙動がびみょーーに異なる点は基本的に以下です
・正規表現や特殊記号を含んだPATTERNを使う
・シングルクォート, ダブルクォート, 囲いなし, PATTERNを使う

まず大きな分かれ道として、

コマンドライン(shell)をなにを使うか

で挙動が異なります。

Windowsでのメジャーなシェルといえば、cmd.exe or powershell.exe です。

①cmd.exeの場合
結論からいえば、
cmd.exe上での[PATTERN]にはダブルクォーテーションをつけましょう。

cmd.exeの場合、PATTERNの文字がダブルクォーテーションがない場合、
引数としてダブルクォーテーションをつけて渡しているような挙動になりました。

例えば以下のようなテキストtest.txtがある場合

aaa
'aaa'
C:>pt --nogroup aaa
test.txt:1:aaa
test.txt:2:'aaa'
C:>pt --nogroup "aaa"
test.txt:1:aaa
test.txt:2:'aaa'
C:>pt --nogroup 'aaa'
test.txt:2:'aaa'

C:>pt -e --nogroup ^aaa
test.txt:1:aaa
test.txt:2:'aaa'
C:>pt -e --nogroup "^aaa"
test.txt:1:aaa
C:>pt -e --nogroup '^aaa'
test.txt:2:'aaa'

結果は見ての通りですが、特徴としては以下の感じです。
・シングルクォートは記号自体がそのまま検索文字として使われる
・正規表現目的の[^]がダブルクォーテーション囲み以外の場合正常に解釈されない

通常grepだとダブルクォートの場合変数を展開、シングルクォートの場合変数展開しないという意味だったと思いますが、
上記のような結果になりました。

ここで、少しだけ調べてみました。

http://thinca.hatenablog.com/entry/20100210/1265813598
資料はあまりないらしいですが、こちらでとても検証されてました。

というか、cmd.exeのエスケープ文字って[^]だったの!?

という驚きの事実があかされました。

つまり正規表現自体が効かないというよりは、^がエスケープ文字として処理されてるゆえだったんですね。

と、謎が少しとけたものの・・・・cmd.exeのカオス具合がよくわかりました。

ここでひとつの結論にたどり着きました。


grep系のコマンドをcmd.exeで真面目にやろうとするのはやめる

そんなわけで以下の検証に続いていきます。

もし、それでも、どうしても、cmd.exeを使う場合、基本ダブルクォートありきで実行するのが一番意図通りの挙動をとるかなと思います。

②powershell.exeの場合

PS C:> pt --nogroup aaa
test.txt:1:aaa
test.txt:2:'aaa'
PS C:> pt --nogroup "aaa"
test.txt:1:aaa
test.txt:2:'aaa'
PS C:> pt --nogroup 'aaa'
test.txt:1:aaa
test.txt:2:'aaa'
PS C:> pt --nogroup "'aaa'"
test.txt:2:'aaa'

PS C:> pt -e --nogroup ^aaa
test.txt:1:aaa
PS C:> pt -e --nogroup "^aaa"
test.txt:1:aaa
PS C:> pt -e --nogroup '^aaa'
test.txt:1:aaa

という感じで、シングルクォートもダブルクォートも囲みなしも意図通りの動作をしました。
というわけで、powershellのほうが安定して使いやすい気がします。
理由は不明です、ここが重要なわけじゃないので調査もしてないので誰か知ってたら教えてください^^;

というわけで、結論としては、シェルとしての機能も充実してるpowershellを使っていきましょう。

vimとptを併用する

そもそも、なんでcmd.exeとpowershell.exeの比較なんて始めたかというと、

vimでptを使って検索をしたときに、思ったように動かなかったんですね。

で、まずはコマンド自体の挙動を確認しようとcmd.exeで試し始めたら、そっちもうまくいったりいかなかったりで・・
みたいな感じで上の調査になりました。

というわけで本来の目的、Windows上でvimからptをいい感じに使う準備です。

まず、vimからptの実行のためのpt.vimプラグインがありますのでこれをインストール。
それからpt.exeはパスを通しておきましょう。

これでvim上のコマンドとして(外部コマンドではなく)

:Pt

ができるようになります。

これでかんたんなワードなどの検索(vimgrepの代わり)は高速にできるようになります。

ここで、サンプルを増やします。このへんがしっかり検索できるようになりたいのが自分の元々の目的です。

aaa
'aaa'

%aaa

ふつーにワード検索は問題ないので、まず正規表現ありパターン。

:Pt -e ^aaa

test.txt|1| aaa
test.txt|2| 'aaa'
test.txt|3| 
test.txt|4| %aaa
:Pt -e "^aaa"

test.txt|1| aaa

次にシングルクォートしてみる。

:Pt 'aaa'
test.txt|2| 'aaa'

はい、まぁ大体お察しの通り、cmd.exeで実行したときと同じ結果です。

まぁそらそうです、以下のとおり

:set shell?
shell=C:WINDOWSsystem32cmd.exe

vimのshellがcmd.exeに設定されているんですもの。
pt.vimの中身詳細はわかりませんが、基本はptを外部コマンドとして実行した結果をquicklistに取り込んでるようなものだと思うので、shell実行環境が依存してくると思われます。

というわけで、より安定した挙動だったpowershellをshellにしたいと考えます。
_vimrcへ以下を追加します。

if has('win32')
    set shell=powershell.exe
    set shellxquote=
endif

shellxquoteは:hするとわかりますが、powershellを指定するとshellxquote=”になります。

つまり、powershellにコマンドを渡すときに例えば、結果的に

pt -e ^aaa
を実行するときに
"pt -e ^aaa"
としてくれる

ということです。

が、このまま:Ptすると、検索結果がおかしなことになってしまいます。
(外部コマンドで:!ptは大丈夫だったんですけどね・・)

で、とりあえずshellxquoteを空にしてコマンド文字列まんま渡しを試してみたらうまくいったという次第。

これで他に不具合がでたらやめるか、なにか考えますが、ひとまず、これで目的を達したのでよしとしました。
(ちゃんとわかるにはpowershellやvimrunの仕様を把握していかないとなんだけど時間がかかるのでまた今度。)

これで正規表現つきの:Ptができる環境が整いました。

やったーーこれで思い通りだああああ、終わり!

と思って色々試してみたら、まだ終わってなかった・・

ただダブルクォートするだけじゃ、事足りない特殊文字が現れました。

“%”, “#” です。(他にもvimで予約してるやつは色々あるのかも。確認したのはこれだけ)

vimのコマンドモードでは、%はカレントファイル名、#は代替ファイル名(:h :_%などを参照)、を表す記号です。

ま、特殊記号ならとエスケープすればいけるはず~

ということで

:Pt %aaa

とやってみるも “%aaa”ヒットなし との結果。

結果だけ見るとちゃんとエスケープされて”%aaa”という文字になっているようですがヒットしません。
これ、ヒットなしということは検索が走ってはいるので、もしやと思い
test.txtに
test.txtaaa
を追記した状態でもう一度処理(test.txtとカレンドディレクトリが同じ状態)するとヒット。

すなわち、エスケープできてないんですね。

pt.vimの中の処理は見てない(見てすぐわかるほどVimscriptに精通してない)ですが、
Vimのコマンドモードでのエスケープ後の文字列を再度エスケープが必要な状態の検索コマンドとして実行されてしまっているのかな
と予想しております。

というわけで、詳細な理由はわかってはいないものの、


Vimのコマンドモードでの特殊記号はエスケープ2回が必要です。

以上、ながなが見てきた割に、本質の理由は突き止めてないところが多くて不甲斐ないですが、
(そこを調べだすとながいんで・・。)
ひとまず、WindowsでVimでptで、高速に正規表現付きや、特殊記号込みで検索できる環境ができました。

Sponsored Link

フォローする