g / re / pを使用して改行文字を変更することがVimの他のすべての行でのみ機能するのはなぜですか?

g / re / pを使用して改行文字を変更することがVimの他のすべての行でのみ機能するのはなぜですか?

考慮する:

foo
bar
....
bar
baz

それから:

:g/bar/s/\n/\r\r/g

予期しない収益:

foo
bar

bar
bar

bar
bar

...
baz

各後ろに新しい行が必要なときbar。しかし:

:g/bar/p

返品:

bar
bar
...
bar

期待どおりにすべてのsの間に改行文字がある場合、bar期待される結果が得られます。各行には、次barの方法で問題を解決しました。

:%s/\(bar.*\)\n/\1\r\r/g

しかし、私は何が起こっているのかをよりよく理解したいと思います。

答え1

このレベルの詳細を理解するには、ソースコードを取得する必要があると思います。したがって、引用してくださいvim-7.1.314/src/ex_cmds.c(ヘッダーを定義するコメントex_global())。

これは2つのステップで行われます。まず、ファイルからパターンを検索し、一致する(一致しない)各行にフラグを設定します。次に、表示された各行でコマンドを実行します。これは、行を削除した後に次の一致を検索する場所がわからないために必要です。

したがって、'edコマンドから1行を削除すると、:gその行の表示も消えます。 'ed コマンドに行を作成すると:g表示されないため、コマンドは実行されません。例では、行3は行2にリンクされているため、行3のマーカーは消え、行2の後のマーカーは元の行4に配置されたマーカーです。

また、変数がex_global設定され、一部のコマンド(含まれている)が少し異なる動作をしますglobal_busy:sしかし、ここではその違いは重要ではないと思います。

答え2

ザイルズすでに「なぜ?」に答えていますが、欲しいものを達成するためのより簡単な方法に興味があると思いました。

私はそれぞれ次に新しい行が欲しいですbar

行終端文字を置き換える代わりに(したがって行を連結し、Gilesの回答に従って内部トークンが失われる)、一致する各行の最後の前に空の行を追加します。$行が終わる前に幅が0の一致を取得するために使用され、そこに改行文字を挿入します(/gパターンは1行に1回だけ一致するため、修飾子は必要ありません)。

:g/bar/s/$/\r/

関連情報