vimで:g /^$/,/./- j(複数の空白行を1つの空白に減らす)はどのように機能しますか?


21

Vim Regular Expressionsの記事で、Oleg Raiskyは複数の空白行を単一の空白に減らすために次のコマンドを提供しています。

:g/^$/,/./-j

誰かがこれがどのように機能するか説明してもらえますか?

:gコマンドと正規表現を知っています。しかし、この部分/,/./-jが何をするのか理解できませんでした。

回答:


24

本当に独創的です。分解しましょう。exコマンド

g/^$/xyzzy

すべての空の行を検索し、各行でxyzzyコマンド(任意のexコマンド)を実行します。xyzzyこれは実際の exコマンドではなく、次の段落のようにプレースホルダーとしてのみ存在することに注意してください。

ここで注意が必要なのはxyzzy、あなたのケースの「コマンド」がさらに別の検索コマンドであることです。

,/./-j

,/./-範囲を指定します。これは形式で<start>,<end>あり、コンマの前に何もないため、現在の行(空行を見つけた行)が開始であると想定します。

カンマの後は/./-、次の文字を検索することを意味し(.任意の文字を意味します)、1行をバックアップします(値が指定されていない場合は1行が暗示さ/./-れる/./-1ため略します)。このパターン.は、操作している行に続く最初の非空白行にあります。

つまり、範囲の最後は、現在操作している行の後または最後の空行です。

次に、その範囲で結合を実行します。

範囲の開始と終了が等しい場合(セクションに空白行が1つしかなかった場合)、joinは何もしません。それらが等しくない場合、joinはそれらをすべて結合します。

これが、複数の空白行を1つに結合する方法です。

例を見てみましょう(行番号は説明のためだけであり、実際のファイルにはありません):

1 Line 1
2
3 Line 3
4 Line 4
5
6
7
8
9 Line 9

このg/^$/コマンドは、すべての空の行を見つけて、それらに対して操作を実行します(これらは行2、5、6、7、および8です)。

2行目で,/./-jは、2〜2の範囲を設定します(次の.行は3行目にあり、1を引いて2を取得します)。範囲2,2での結合は何も行いません。

5行目で,/./-jは、5〜8の範囲を設定します(.9行目で次に1を引く)。範囲5,8での結合は、これらすべての行を結合します。

操作は、以前の操作の一部として消える行では実行されません。これは、サイクルの早い段階で削除された行を処理する意味がないためです。

言い換えれば、6行目から8行目が削除されるため(5行目と組み合わせて)、その後、グローバルコマンドはそれらに対して動作しません。

これは、vimドキュメントが2パスアルゴリズムを記述しているという事実に基づいています。1つは行をマークし、もう1つは操作を実行します。


2
ファイルの最後に空の行がある場合、このコマンドは文句を言うことに注意してください。
ワイルドカード
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.