327

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

行ごとに手動でコピーして貼り付けずにこれを行う良い方法はありますか?

4

9 に答える 9

885

確かに、これらすべてを 1 回のコピー/貼り付け (ブロック モード選択を使用) で行うことができますが、それはあなたが望んでいることではないと思います。

Exコマンドだけでこれを行いたい場合

: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
~

更新:この多くの賛成票を含む回答は、より完全な説明に値します。

Vim では、パイプ文字 ( |) を使用して複数の Ex コマンドを連結できるため、上記は次のようになります。

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

多くの Ex コマンドは、行の範囲を前置引数として受け入れます。上記の場合、コマンドが動作する行を指定する前5,8del1,4前のです。s///

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

more than 
hour 
our 
never 
ever
after
work is
over
~

「work is」が 2 つのリスト要素に分割されるのを防ぐために、別の区切り文字を指定する必要がありますlet l=split(@","\n")

最後に、置換s/$/\=remove(l,0)/では、各行の終わり ( $) を式の値に置き換えますremove(l,0)remove(l,0)listlを変更し、最初の要素を削除して返します。これにより、削除された行を読み取った順に置き換えることができます。代わりに、 を使用して、削除された行を逆の順序で置き換えることができremove(l,-1)ます。

于 2012-05-25T19:44:06.780 に答える
58

:global、、、:moveおよびコマンドを組み合わせることで、問題を解決するエレガントで簡潔なExコマンドを取得でき:joinます。行の最初のブロックがバッファの最初の行から始まり、カーソルが2番目のブロックの最初の行の直前の行にあると仮定すると、コマンドは次のようになります。

:1,g/^/''+m.|-j!

この手法の詳細な説明については、同様の質問「<ahref="https://stackoverflow.com/q/9658612/254635">箱から出して「貼り付け-d」」の動作を実現する方法に対する私の回答を参照してください。 Vimで?」

于 2012-05-26T07:09:30.270 に答える
45

行のブロックを結合するには、次の手順を実行する必要があります。

  1. 3 行目に移動します。jj
  2. ビジュアル ブロック モードに入る:CTRL-v
  3. カーソルを行末に固定します (行の長さが異なる場合に重要です)。$
  4. 最後に移動します。CTRL-END
  5. ブロックをカットする:x
  6. 最初の行の最後に移動します。kk$
  7. ここにブロックを貼り付けます:p

動きは最高のものではありません (私は専門家ではありません) が、希望どおりに動作します。それの短いバージョンがあることを願っています。

この手法がうまく機能するための前提条件は次のとおりです。

  • 開始ブロックのすべての行 (質問の例abcdef) は、同じ長さのXORを持ちます。
  • 開始ブロックの最初の行が最も長く、その間の追加のスペースは気にしません) XOR
  • 開始ブロックの最初の行は最長ではなく、最後にスペースを追加します。
于 2012-05-25T19:41:02.217 に答える
19

これを行う方法は次のとおりです(最初の行にカーソルを置きます):

qama:5<CR>y$'a$p:5<CR>dd'ajq3@a

次の 2 つのことを知っておく必要があります。

  • 2 番目のグループの最初の行が始まる行番号 (私の場合は 5)、および
  • 各グループの行数 (私の例では 3)。

何が起こっているかは次のとおりです。

  • qaqの「バッファ」に次までのすべてを記録しますa
  • ma現在の行にマークを作成します。
  • :5<CR>次のグループに行きます。
  • y$行の残りをヤンクします。
  • 'a以前に設定したマークに戻ります。
  • $p行末に貼り付けます。
  • :5<CR>2 番目のグループの最初の行に戻ります。
  • dd削除します。
  • 'aマークに戻ります。
  • jq1 行下に移動し、記録を停止します。
  • 3@a行ごとにアクションを繰り返します(私の場合は3)
于 2012-05-26T00:54:59.103 に答える
8

他の場所で述べたように、ブロック選択が有効です。ただし、次のバリアントを使用することもできます。

:!tail -n -6 % | paste -d '\0' % - | head -n 5

この方法は、UNIX コマンド ラインに依存しています。このpasteユーティリティは、このような行のマージを処理するために作成されました。

PASTE(1)                  BSD General Commands Manual                 PASTE(1)

NAME
     paste -- merge corresponding or subsequent lines of files

SYNOPSIS
     paste [-s] [-d list] file ...

DESCRIPTION
     The paste utility concatenates the corresponding lines of the given input files, replacing all but the last file's newline characters with a single tab character,
     and writes the resulting lines to standard output.  If end-of-file is reached on an input file while other input files still contain data, the file is treated as if
     it were an endless source of empty lines.
于 2012-05-26T04:18:02.667 に答える
3

あまり複雑にすることはないと思います。
( :set virtualedit=all)
Select ブロック 123 以下に virtualedit を設定するだけです。
最初の列の後に入れます。

abc    123
def    45
...    ...

1 つのスペースとの間の複数のスペースを削除します。

:%s/\s\{2,}/ /g
于 2013-06-07T09:01:53.543 に答える
3

サンプルデータはramionのものと同じです。

:1,4s/$/\=getline(line('.')+4)/ | 5,8d
于 2012-07-20T06:11:41.963 に答える
2

複雑な繰り返しを使用します:)

これを考えると:

aaa
bbb
ccc

AAA
BBB
CCC

最初の行にカーソルを置いて、次のように押します。

qa}jdd''pkJxjq

を必要な回数だけ押し@aます (後で を使用することもできます)。@@

最終的には次のようになります。

aaaAAA
bbbBBB
cccCCC

(さらに改行。)

説明:

  • qaで複雑な繰り返しの録音を開始しますa

  • }次の空行にジャンプします

  • jdd次の行を削除します

  • ''最後のジャンプの前の位置に戻る

  • p削除された行を現在の行の下に貼り付けます

  • kJ現在の行を前の行の末尾に追加します

  • xJ結合された行の間に追加されるスペースを削除します。スペースが必要な場合は、これを省略できます

  • j次の行に移動

  • q複雑な繰り返し録音を終了する

その後、 を使用@aして に格納された複雑な繰り返しを実行し、を使用して最後に実行された複雑な繰り返しを再実行aできます。@@

于 2012-07-14T15:39:10.483 に答える
1

これを達成する方法はたくさんあります。次の 2 つの方法のいずれかを使用して、2 つのテキスト ブロックをマージします。

最初のブロックが 1 行目にあり、2 番目のブロックが 10 行目から始まり、カーソルの初期位置が 1 行目であるとします。

(\n はエンターキーを押すことを意味します。)

1. abc
   def
   ghi        

10. 123
    456
    789

コマンドを使用したマクロ: コピー、貼り付け、および結合。

qaqqa:+9y\npkJjq2@a10G3dd

コマンドを使用したマクロで、n 番目の行番号で行を移動して結合します。

qcqqc:10m .\nkJjq2@c

于 2014-02-15T16:20:38.470 に答える