すべての行をどのパターンに一致させるのですか?


11

特定のパターン(など;)がある行に対してのみ行を結合したいのですが、g/;/j数回呼び出さないと、期待どおりに機能しません。

たとえば、次のコンテンツ:

a
1;
2;
3;
4;
5;
b
6;
7;
8;
9;
c

使用時::g/;/j出力は次のとおりです。

a
1; 2;
3; 4;
5; b
6; 7;
8; 9;
c

または:g/;/-j与える:

a 1; 2; 3; 4; 5;
b 6; 7; 8; 9;
c

と似ています:g/;\_.\{-};/j

私の予想される出力は:

a 
1; 2; 3; 4; 5;
b
6; 7; 8; 9;
c

または似たようなものなので、パターンを含むすべての線が結合されます。

どうすればこれを達成できますか?


3
FWIW :g/;/jは2つのパスで行われるため機能しません。最初にバッファがスキャンされ、次にコマンドが一致する行に適用されます。
romainl 2015

回答:


12

問題の考えられる説明

:g/;/j動作しない理由は、:gコマンドが2パスアルゴリズムで動作するためです。

  • 最初のパスでは、パターンを含む行をマークします ;
  • 2番目のパスでは、マークされたラインで動作します

2番目のパスで:gは、最初のパスでマークされたため、ライン1;とラインを結合します。しかし、私はそれが参加していないこと(ないように注意してください)疑いでラインがあるため、もはや存在しない、その内容は、ラインにマージされましたすでに処理されています。 2;1;1; 2;3;2;1;

したがって:g、最初のパス(3;)でマークされた次の行を探し、次の行()と結合し4;ます。問題が繰り返された後、それは参加できない3; 4;との5;ラインがあるため4;、もはや存在しません。

ソリューション1(vimscriptを使用)

たぶん;、前の行にセミコロンが含まれているかどうかを確認するために、含まれている行が見つかったときに関数を呼び出すことができます。

function! JoinLines()
    if getline(line('.')-1) =~ ';'
        .-1join
    endif
endfunction

次に、次のグローバルコマンドを使用します。

:g/;/call JoinLines()

または関数なし:

:g/;/if getline(line('.')-1) =~ ';' | -j | endif

ソリューション2(vimscriptなし)

:g/;/.,/^[^;]*$/-1j

グローバルコマンド:gがパターンを見つけると、コマンドを;実行します。 .,/^[^;]*$/-1j

次のように分解できます。

:g/pattern/a,bj

どこ :

pattern = ;
a       = .           = number of current line
b       = /^[^;]*$/-1 = number of next line without any semicolon minus one

b 次のようにさらに分解できます:

/    = look for the number of the next line matching the following pattern
^    = a beginning of line
[^;] = then any character except a semicolon
 *   = the last character can be repeated 0 or more times
 $   = an end of line
 /   = end of pattern
 -1  = removes one to the number you just got

jExコマンドの省略形で、:join他のほとんどのExコマンドと同様に、範囲を前に付けることができます。
ここでは、範囲が先行しています:.,/^[^;]*$/-1a,b
範囲の形式以下と一般に2行番号であるが、あなたは番号の間にある行のグループ上で動作することを可能にすると、代わりに一つだけの。 a,babab

したがって、このjコマンドは、現在の行(a)と、セミコロンから1を引いたものを含まない次の行()までのすべての行を結合しますb

詳細については、以下を参照してください。

:help :global
:help :join
:help :range

1

私はグローバル検索で常に同じように参加して置き換えます:

s /; \ n /; /

\n 改行と一致します。

空白行を見つけて削除するには:

s / ^ $ \ n //

理由はわかりませんが、新しい行を挿入したい場合は、 \r


s単独では1行だけで機能し、それをグローバルにするにはを使用する必要があり%sますが、それ以外の;行を含むほとんどすべての行に参加します
kenorb

2
@kenorbエームいや、:sあなたが望むものに正確にコマンドを使用できると思います。これ%s/;\n\(.*;\)\@=/;/はあなたが必要としていることだと思います。
クリスチャンブラバンド2016年
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.