web-dev-qa-db-ja.com

vim正規表現でネガティブな先読みを行う方法はありますか?

Vimで、abcと一致するが、行の後半にxyzが含まれていない行を検索する方法はありますか?したがって、次の行が一致します。

The abc is the best
The first three letters are abc

そして、以下は一致しません:

The abc is the best but xyz is cheaper
The first three letters are abc and the last are xyz

私は次のような構文について知っています:

/abc\(xyz\)\@!

ただし、これはabcxyzの一致を回避するだけであり、abc-xyzなどの間に何かがある場合は回避しません。使用する

/abc.*\(xyz\)\@!

また、行の後半にxyzが一致しない位置が多数あるため、機能しません。

(コマンドラインでgrep abc <infile | grep -v xyzのようなことをしますが、Vimで上記をインタラクティブに実行したいことに注意してください。)

32
Greg Hewgill

あなたの試みはかなり近かった。 .*をプルして、一致と後でアサートされた不一致の間の任意の距離を許可する必要があります負の先読みに

/abc\(.*xyz\)\@!

.*のすべての可能な一致に対して不一致が試行され、すべてのブランチが使い果たされた場合にのみ\@!が満たされていると宣言されるため、これは機能すると思います。

32
Ingo Karkat

あなたの質問は先読みについてですが、私は後読みを探しているときにそれを見つけました。したがって、他の人がそれを見つけることができるように、私は後ろ向きに解決策を投稿します。

pattern2が前に付いていないpattern1を検索する場合、つまりネガティブルックビハインドの場合は、次を検索します。

\(pattern1\)\@<!pattern2
5
hochl

私はいつも奇妙だと思っています。vimで角かっこをエスケープする必要があるので、ほとんどの場合、\vでアクティブ化される「非常に魔法の」モードを使用しようとします。

/\vabc(.*xyz)@!
4
hansaplast

これは私のために働きます/abc\(.*xyz\)\@!

2
priomsrb

これを/abc\(\(xyz\)\@!.\)*$と書くと思います

これが他の提案よりも速いかどうかはわかりませんが(各位置を1回だけテストするためかもしれません)、概念的には次のように意味があります。

「abcの後にxyz以外のものが続く、行末まで何度でも」

上記の他のパタ​​ーンのように、「abcの後にxyzが続かないものが続く」よりもそれが好きです。

0
Ben