1. ホーム

[解決済み】Vimで2つの複数行のテキストブロックをマージする方法は?

2022-03-26 23:19:15

質問

Vimで2つの行のブロックをマージしたいのですが、つまり、行を取る  k を通して  l の行に追加してください。 m を通して  n . 擬似コードでの説明がお好みなら [line[k+i] + line[m+i] for i in range(min(l-k, n-m)+1)] .

例えば

abc
def
...

123
45
...

になるはずです。

abc123
def45

一行ずつ手作業でコピー&ペーストすることなく、これを行う良い方法はないでしょうか?

どのように解決するのですか?

ブロックモード選択で)1回のコピー&ペーストで全部できるのは確かですが、あなたが望んでいるのはそれではないでしょう。

もし、これを コマンド

:5,8del | let l=split(@") | 1,4s/$/\=remove(l,0)/

を変換します。

work it 
make it 
do it 
makes us 
harder
better
faster
stronger
~

に入っています。

work it harder
make it better
do it faster
makes us stronger
~


UPDATEです。 これだけのアップヴォートを得た回答は、もっと徹底的な説明が必要です。

Vimでは、パイプ文字( | ) を使って、複数のExコマンドを連結することができます。

:5,8del
:let l=split(@")
:1,4s/$/\=remove(l,0)/

多くのExコマンドは、プレフィックス引数として行の範囲を指定することができます。 5,8 の前に del1,4 の前に s/// は、コマンドがどの行で動作するかを指定します。

del は、指定された行を削除します。 これは、レジスタ引数を取ることができますが、引数が与えられない場合、無名のレジスタに行をダンプします。 @" 通常モードでの削除と同様です。 let l=split(@") で、削除された行をリストに分割し、デフォルトの区切り文字である空白を使用します。 削除された行に空白があるような入力に対して正しく動作させるには、次のようにします。

more than 
hour 
our 
never 
ever
after
work is
over
~

が2つのリスト要素に分割されるのを防ぐために、別のデリミタを指定する必要があります。 let l=split(@","\n") .

最後に、代入で s/$/\=remove(l,0)/ というように、各行の最後を置き換えます ( $ という式の値に置き換えてください。 remove(l,0) . remove(l,0) はリストを変更します。 l で、その最初の要素を削除して返します。これにより、削除された行を読んだ順番に置き換えることができます。代わりに、削除された行を逆順に置き換えるには remove(l,-1) .