n行を削除して1行のスクリプトをスキップ


10

単にn行を削除し、1行をスキップして、ドキュメントの最後まで繰り返す基本的なVimスクリプトを作成したいと思います。特定の一致は気にせず、行を削除したいだけです。例えば; したがって3ddj、ドキュメント全体に対してコマンドを繰り返したいと思います。

Text I want to keep.   
Text I want to delete.  
Text I want to delete.  
Text I want to delete.  
Text I want to keep.  
Text I want to delete.  
Text I want to delete.  
Text I want to delete.  
Text I want to keep.  
Text I want to delete.  
Text I want to delete.  
Text I want to delete.   

だから…

Text I want to keep.  
Text I want to keep.  
Text I want to keep.  

ありがとうございました。


regular-expression質問にタグを含めましたが、正規表現でこれを行う理由を質問が指定していないようです。正規表現を使用するものを実際に探している場合は、stackoverflow.com / questions / 17735289 / …が役立ちます。その質問はNotepad ++に関するものでしたが、答えはpcre regexのみを使用しています。(免責事項:私はその答えを書きました。)
ジャスパー

次回質問するときは、「ありがとうございます。素晴らしい解決策です!」と書く必要はありません。すべての答えに。これは、回答に新しいコメントを作成しようとしたときにも書き出されます。
パイプ

これに加えて、ここで感謝を示す適切な方法は、あなたにとって最も効果的な答えを受け入れ、あなたが役立つか有用だと思う答えを賛成することです。人々は「感謝」のコメントよりもむしろそれを見てみたいです。
Bレイヤ

回答:


19

非常にシンプルなアプローチ:

  1. 削除する最初の行に移動します。
  2. マクロを記録します。 qa3ddjq
  3. 高い数値で繰り返します:1000 @ a

ステップ3では、マクロが1000回、またはエラーが発生するまで繰り返されます。ファイルの終わり(したがって削除する行がない)を押すと、エラーが発生し、マクロの繰り返しがキャンセルされます。

を参照してください:help recording


2
すごい!!! どうもありがとう、それは私のために働いた:D
マックス・コプリー

1
説明:( qコマンドモード、およびvimまたは他の最近の代替バージョン[neovimなど]で、元のviではない)は、「記録を開始し、それを「次の文字」バッファーに入れる」ことを意味します。したがってqa、「「a」バッファーへの記録を開始する」という意味です。次に、この後に入力されたすべてのキー(qコマンドモードの次のキーまで)が記録されます(記録することもできます:編集モードに入る、何かを入力する、コマンドモードにエスケープするなど)。次に12@a、バッファー "a"に記録されたアクションを12回繰り返します。
Olivier Dulac

3
さらに、1000@q最後に何かを実行したくない場合は、再帰的マクロを作成できます:最初に空にするqa3ddj@aq@a必要があるかもしれませんが、qaq最初に実行する必要があるかもしれません"a
ジェームズ

17

私にとって最も簡単な解決策は:

:%norm j3dd

あれは:

  • %:すべての行
  • norm:次のキーを通常モードと同じように実行します
  • j3dd:行を下に移動してから3行を削除

したがって、最初の行から2行目に移動し、次の3行を削除します。Text I want to keep.2行目は2行目になります。1行下に移動し、3を削除します。すすぎ、繰り返します。


注:ファイル全体を処理したくない場合は、で置き換えることができます。%normたとえば5,$norm、5行目からファイルの最後まで処理します。


4
とてもいい代替品です!vim(viではない)で動作します。これまで「規範」について聞いたことがありません!(そして私は一種のvi [m]オタクです)
Olivier Dulac

6

あなたはすでに利用可能ないくつかの素晴らしいソリューションを持っています。ここに別のものがあります:

:g/^/if line('.')%4!=1|:s/^/DELETE ME/|endif
:g/^DELETE ME/d

まず、すべての行:gに対してアクションを実行し^((行の先頭)と照合)、すべての行番号に対しての結果を実行しlinenumber % 4ます。結果がと等しくない場合は、行の先頭に1追加DELETE MEし、次のコマンドで削除する行をマークします。

次のコマンドは、通常の(:g)コマンドであり、で始まるすべての行に一致しますDELETE ME

最初の:gコマンドを使用して行をすぐに削除することはできません。これにより、結果のモジュロ計算が変更されるため、最初に行にマークを付け、2番目のステップでそれを削除する必要があります。


4

私はこれがviチャンネルであることを知っていますが、私にとってこれはsed問題です。

sed -ne 'p;n;n;n' <file >newfile

だからあなたはそれをvi解決策に絞ることができます:

:0
!Gsed -ne 'p;n;n;n'

1
sedソリューションの場合は+1。
Christian Brabandt

3

別の方法(例のテキストのように、1行目から始めて2-4行目、6-8行目などを削除するとします):

while line(".") < line("$")
    silent +1delete _ 3
endwhile

これをインタラクティブに実行したい場合は、「コマンドラインレジスタ」を利用できます。つまり、

:+1del 3<CR> その後 1000@:


1

別の方法:行を保持したい場合:1、4など。

awk '!((FNR-1)%3)'  file > newfile
      # awk: when a condition is given without action:
      #        prints the lines for which the condition returns 0.
      # FNR designates the line number in the current file.
      # a%3 : takes the modulus of a and 3. ( 0%3=0, 1%3=1, 2%3=2, 3%3=0, 4%3=1, etc.) 
      # This will be 0 for 3, 6, etc. 
      # But we want it to be 0 (true) for 1, 4, etc : so we substract 1 to NR

# to see that it keeps those lines:
seq 1 20 | awk '!((NR-1)%3)'
1
4
7
10
13
16
19

別の代替方法:必要な行が特定のパターンに一致することがわかっている場合:

# for exemple each line you want contains "some pattern":
fgrep "some pattern" file > newfile
# (or regular grep if you want "some pattern" to be interpreted as a regexp)
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.