vimを使用して、次の2行を変換しようとしています
output reg [1:0] abcd,
output reg efgh,
の中へ
abcd
efgh
正規表現を使用していますが、
:%s/\voutput|reg|\s*|\[.*\]|,//g
しかし、私は次のように出力を得ています、
[1:0]abcd,
efgh,
どんな助けにも感謝します!ありがとう。
:help pattern
理由を示します(ただし、以前にさまざまな可能性にさらされたことから理由を推測することは非常に役立ちます:-)
1. A pattern is one or more branches, separated by "\|". It matches anything
that matches one of the branches. Example: "foo\|beep" matches "foo" and
matches "beep".
If more than one branch matches, the first one is used.
Vim の正規表現マッチャーは、最初に一致するエンジンです。POSIX では、一番左が一番長いことが義務付けられています。純粋主義者は、他のものは正規表現マッチャーではなく、「パターンマッチャー」にすぎないと主張するかもしれません.vimがそれらを「パターン」と呼んでいることと関係があるかもしれません... sed
そしてperl
左端が最も長いです:
$ sed -r 's/output|reg|\s*|\[.*\]|,//g' @@
abcd
efgh
$ perl -ple 's/output|reg|\s*|\[.*\]|,//g' @@
abcd
efgh
ただし、最初の一致エンジンでは、少し異なることを行う必要があります。代替案を並べ替えると、次のように機能します。
:%s/\voutput|reg|\[.*\]|,|\s*//g
と置き換える\s*
と\s+
、順序に依存しなくなります。
:%s/\voutput|reg|\s+|\[.*\]|,//g
Vim のg
フラグは、最初に一致したブランチの出現をすべて置き換えてから、何も変わらなくなるまで再試行するようです。
完全で紛らわしいだけですが、
:%s/\v(reg|output|\s*|\[.*\]|,)*//
abcd,
efgh,
と
:%s/\v(reg|output|\s*|\[.*\]|,)*//g
abcd
efgh
上記で推測されたルールを考えると、これは少しの間、実際に意味がありました。
(編集: gawk
sgensub
およびnvi
sextended
エンジンも明らかに左端が最も長い)
正規表現の問題は、\s* を要求する部分です。これは、文字通り「空白がない、または空白が多い」ことを意味します。そして、正規表現全体が 1 つの大きな OR であるため、Vim は少なくとも 1 つの空白が見つかるまで文字列を消費し始めます。これが発生すると、再び OR の最初からマッチングを開始し、プロセスを繰り返します。したがって、\s* は空白文字が見つかるまで必要なだけ消費できるため、\s* の後に受信しようとしている式は無視されることを意味します。これを確認するには、\s* の位置を変更すると異なる結果が得られることに注意してください。これは、\s* の前の式のみを削除することになります。
あなたが実際に望んでいた正規表現は次のとおりだと思います:
:%s/\voutput|reg|\s+|\[.*\]|,//g
少なくとも空白がある場所を置換したいことを示すため。これは私にとってはうまくいきました。
正規表現が機能しなかった理由。
vimは正規表現を左から右に読み取り、ユニオンの各セクションを順番に一致させようとするようです。
したがってoutput|reg|\s*|\[.*\]|,
、すべての文字の間にある\[.*\]
空の文字列が一致するため、に到達することはありません。\s*
vim 正規表現エンジンは何かに一致したため、すぐに置換を行います。
is lastのユニオンを並べ替えるだけで\s*
、正規表現は期待どおりに機能します。
したがって、コマンドは:%s/\voutput|reg|\[.*\]|,|\s*//g
これは機能します(末尾近くの4つのアルファベットを探します):
%s/^.*\<\(\a\{4}\),\s*$/\1/g