4行ごとに反転する方法は?


13

まず、これが私の最初の投稿であるため、VIMが優れたツールであり、フォーラムが質問への回答を見つけるのに非常に役立ち、多くの役立つ人々が提供していることを伝えたいと思います貴重な支援。私はまだVIMが初めてなので、ここで学んだことのほとんどすべてがここから来ています。

私の質問は、ファイル内のすべての行を反転する方法を知っています(他の方法の中でも:g / ^ / m0)が、ファイル内の4行ごとに反転する方法がありますので、

line1
line2
line3
line4
line5
line6
line7
line8
...

になる

line4
line3
line2
line1
line8
line7
line6
line5
...

このようなファイルには、常に4行の正確な倍数が存在すると想定できます。


2
「ps」について:行の前に4つのスペースを挿入すると、コードとして解釈されます(テキストを選択し、上部の形式ボタンを使用できます)。上部の質問アイコンの詳細を確認できます。
mMontu

回答:


15

Vim Wikiで:Reverse説明されているコマンドをこれに使用できます(.vimrc永続的にするためにコマンドを含めることができます)。

command! -bar -range=% Reverse <line1>,<line2>g/^/m<line1>-1|nohl

その後、4行ごとにコマンドを実行するマクロを記録できます。

qmV3j:Reverse<cr>4jq
1000@m

説明:

  • qm:通常モードの 'q'は、指定されたレジスター(この場合はレジスター 'm'ですが、他の任意の文字)でマクロの記録を開始(および停止)します
  • V:ビジュアルモードに入り、現在の行を選択します
  • 3j:視覚的な選択を次の3行に展開します
  • :Reverse<cr>:選択した行でReverseコマンドを実行します(<cr>ここではenterキーを表します)
  • 4j:次の変更されていない行に移動します
  • q:マクロの記録を停止します
  • 1000@m:レジスタ 'm'に記録されたマクロを1000回実行します(ファイルが4000行を超える場合、この数を増やすことができます)

編集:

コメントで述べたように、カウントを使用する代わりに再帰的なマクロを使用できます。

qmV3j:Reverse<cr>4jq
qM@mq
@m
  • qM:に指定されたレジスタqが大文字の場合、マクロはレジスタに追加されます(これは、複雑なマクロの最後のステップを見逃したことに気づいたときにも役立ちます)
  • @m:登録時にマクロを実行する m
  • q:マクロの追加を停止します

マクロとして作成されますが、ワークフローの一般的なタスクである場合は、このためのコマンドを作成できます。

function! Reverse4()
   let reg_m = @m
   let @m = '<c-r><c-r>m'
   normal! @m
   let @m = reg_m
endfunction
command! Reverse4 call Reverse4()
  • function! Reverse4()/ endfunction:新しい関数を定義します
  • let reg_m = @m:レジスタの現在の内容を保存します m
  • let @m = "<c-r><c-r>m":レジスタにマクロを挿入しますm-これ<c-r>Ctrl+ のvim表記でrあり、コピー/貼り付けではなくこれを入力する必要があるため、行は類似してlet @m = 'V3j:Reverse^M4j@m'おり、特殊文字(^ M)が含まれます
  • normal! @m:通常のコマンドは、通常モードで入力されたとおりに引数を実行するため、再帰マクロを実行します
  • let @m = reg_m:レジスタの内容を復元するmため、この関数でこのレジスタが使用されていることを覚えて、使用を避ける必要はありません

  • command! Reverse4 call Reverse4():この関数の新しいコマンドを作成します

必要に応じて、それを強化することができます。たとえば、コマンドと関数に引数を渡すと、4行のグループで修正されるのではなく、任意の行数で機能します。


1000@qハックの代わりに、再帰マクロを使用することもできますqmqqm ... @mq@m
ドアノブ

「qmV3j:Reverse <cr> 4jq」を実行しようとすると、「E492:エディタコマンドではありません」と表示されました。私は何か間違ったことをしているに違いありません。ちなみに、私はGVIMを使用していますが、これまで使用したことがありません。私はそもそもそれについて言及すべきでした。
ablewasiereisawelba

ああ、気にしないで。私はそれを理解しました-「qmV3j:Reverse <cr> 4jq」の部分の前に「:」と入力することは想定されていません。動いた!どうもありがとう、mmontu。.vimrcに「:Reverse」コマンドを含めるにはどうすればよいですか?
-ablewasiereisawelba

3
@ablewasiereisawelbaコマンドを永続的に使用可能にするにはcommand! -bar -range=% Reverse <line1>,<line2>g/^/m<line1>-1|nohl、vimrcのどこかに行を書きます。
サギノー

@saginawああ、私はそれがそんなに簡単だとは知りませんでした。ありがとうございました。
-ablewasiereisawelba

9

同じように、すべて の繰り返し の行動あなたは基本的な編集操作で一度何かを行うことができれば、あなたは簡単にマクロを記録することによって、それを時間の多くを行うことができます。

(この場合、再帰的なマクロを使用しますが、非再帰的なマクロを記録し、ハンマー@@またはカウントを使用して複数回再生することができます。)

ggqqqqqddjjpkddkkPjddpjj@qq@q

壊れた

  1. gg:ファイルの先頭に移動します。
  2. qqq:レジスタをクリアしますq。手順5でこれが必要な理由を確認します。
  3. qq:qを登録するマクロの記録を開始します
  4. ddjjpkddkkPjddpjj:最初の4行を手動で削除して貼り付けるだけで並べ替える一連の操作。(これは、一見複雑に見えるかもしれませんが、だまされてはいけないこれは、あなたが最初の5分程度の中で学んだだろうと非常に基本的なものです。vimtutorjkddpP
  5. @q:マクロを呼び出します!この時点で、レジスタにqは何も含まれていないため(ステップ2でクリアしたため)、何も起こりません。
  6. q:マクロの記録を停止します。
  7. @q:再帰マクロを必要な回数だけ再生します。

NB上記の例では、ファイルに4で割り切れない行数が含まれている場合、望ましい結果が得られません。残りの4行がない場合にマクロを早期に停止するには、ステップ4で編集の適用を開始するに、失敗するVimの通常モードコマンドを実行する必要があります。行の移動を開始する前に、3行(およびバックアップ)します。jjj3k

したがって:

ggqqqqqjjj3kddjjpkddkkPjddpjj@qq@q

レジスタqを明示的に消去するのはなぜですか?録音するだけで、そこにあったものはすべて上書きされます
ワイルドカード

4
@Wildcardこれは再帰的なマクロであるため、最初にregisterの内容を呼び出すときはq空である必要があります。そうでない場合、エディションが台無しになります。
サギノー

非常に素晴らしい。私はあなたのコマンドの正確な配列を入力し、使用して巻き取るしようとせずに対話的にこれを試してみました:qqqggqqjjjkddkkPjddjpkddkkPjjjj@qq@q
ワイルドカード

1
@ablewasiereisawelba- where I can just use the one-line custom command each time I need to do thisマクロを使用する必要があるたびにマクロを再作成する必要はありません。vimrcにマクロを関数/コマンドとして保存できるためです。
mMontu

1
@ablewasiereisawelba「編集」が便利だとわかってうれしいです!これはここでの最初の投稿であるため、StackExchange通知がどのように機能するかを知らない可能性があります。コメントを投稿すると、回答/質問の作成者が通知を受け取ります。@ <nick>を含めた場合にのみ、他の人に通知が届きます。したがって、Richのみが最後のメッセージに関する通知を受け取りました。
mMontu

7

外部フィルターとしてEx使用するコマンドでこれを行うこともできsedます:

:%!sed -n 'h;n;G;h;n;G;h;n;G;p'

このバージョンは、4の倍数を超える余分な行を無視(削除)します。4行未満の最後のセット(保持)を保持するには、次を使用します。

:%!sed -n '$p;h;n;G;$p;h;n;G;$p;h;n;G;p'

%ここでは、「バッファ内のすべての行」を意味します。

この!コマンドは、「指定された行を入力として次のコマンドを実行し、指定された行をコマンドの出力に置き換える」ことを意味します。(これはフィルターと呼ばれます;並べ替えなどに非常に便利です。たとえば、:%!sortファイル内のすべての行:2,8!sortを並べ替えます; 行2〜8などを並べ替えます)

sedストリームエディタツールであり、すべてのUnixライクシステムで使用されています。sedここで使用される重要な概念は、「パターンスペース」(デフォルトでは入力の各行を順番に含む)と「ホールドスペース」(使用中に余分なテキストを貼り付けてsed他の処理中に保存する場所)です。入力行)。

-nsedパターンスペースを印刷するデフォルトのアクションを抑制するコマンドのオプションです(この場合、明示的に指定した場合にのみ印刷したいため)。

$psedコマンド内の「sed入力の最後の行にいる場合、印刷(パターンスペース)」を意味します。

h 「「パターンスペース」の現在の内容を「ホールドスペース」に貼り付け、そこにあるものを上書きする」という意味です。

n 「「パターンスペース」の内容を入力の次の行に置き換える」という意味です。

G は、「「パターンスペース」に追加します。「ホールドスペース」の内容が続く改行。」

すべてをまとめると、sedコマンドは4行の出力を保存し、保存するときにそれらを反転してから印刷します。$p第二のバージョンに追加のコマンドがファイルの最後の行が4行の倍数に以外に達した場合、ラインがまだ印刷されていることを確認します。


Vim固有の機能を使用せず、外部フィルターも使用しない、代替の対話型アプローチの場合:

:4

4行目に移動します。

:.m -4 | +3m . | +2m . | +5

前の4行(1〜4)を逆にして、カーソルを8行目に残します。

.m -4わずかに移動現在の行を行4行バック(移動行にカーソルを残します)。

+3m .現在の行の3行の行現在の行の直後に移動し、移動した行にカーソルを置きます。 +2m .もちろん同じように機能します。

+5 カーソルを現在の位置から5行下に置きます。

必要に応じて繰り返します。

Vim @:では、このコマンド全体をで繰り返し、次にで繰り返し@@ます。POSIXではviまたはexあなたする必要があります挿入 :.m -4 | +3m . | +2m . | +5、テキストの行としてという名前のバッファ(レジスタ)にそれを削除し、その名前のバッファ(レジスタ)を実行します。

そのため、exモードでは、POSIX指定の機能のみを使用して対話的に行を反転し、17行のテキストから開始します。

Entering Ex mode.  Type "visual" to go to Normal mode.
:0a     # Append following text after "line 0" (i.e. insert at start of file).
.m -4 | +3m . | +2m . | +5
.       # End text insertion
:d k    # Delete that line to register k
line1   # This is a printout of the current line
:4      # Move to line 4
line4
:@k     # Execute register k to reverse lines 1-4
line8
:@@     # Execute register k again
line12
:@@     # Execute register k again
line16
:@@     # Execute register k again
line17
:%p     # Print the whole buffer (just to see what was done)
line4
line3
line2
line1
line8
line7
line6
line5
line12
line11
line10
line9
line16
line15
line14
line13
line17
:wq     # Save and quit

参考文献:


あなたの解決策についてもう少し説明してもらえますか?
-vappolinario

3
@vappolinario、さらに説明を追加しました。それは役立ちますか?:)
ワイルドカード

うわー、非常に長い答え。:)実際にsedしましたが、どこかで見つけた1つの簡単なスクリプト(おそらくこのボード上)で使用しました。これは、私が抱えていた問題の解決策でした。ただし、提案された行を実行しようとすると、「 'sed'は内部または外部コマンド、操作可能なプログラム、またはバッチファイルとして認識されません」と表示されます。vimフォルダーにsedする必要があるのか​​、それとも何なのかわかりません。
-ablewasiereisawelba

1
あなたがWindowsマシン上で実行されているとCygwin(またはMobaXtermまたは類似)を使用していない場合は@ablewasiereisawelba、あなたは私が与えた他の方法を試みることができる。4G:.m -4 | +3m . | +2m . | +5<Enter>@:そして、@@ファイルが完全に処理されるまで繰り返さ。ただし、MobaXtermをインストールすることをお勧めします。:)
ワイルドカード

@Wildcardわかりました、今MobaXtermをチェックしています。:)
–ablewasiereisawelba

7
:g/^/exe 'm .-' . substitute(line('.') % 4, '^0$', '4', '')

平易な英語:すべての行について、現在の行を上lnum % 4lnum % 4 == 0移動し4ます。

また、すべてのn行を逆にするに4は、上記のコマンドのをで置き換えnます。


2
非常に便利な1行のコマンド。ありがとう、djjcast。
ablewasiereisawelba
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.