vimが期待される行に移動しない

vimが期待される行に移動しない

私の究極の目標は、文の区切り記号に基づいてテキストを分割することです。しかし、文章に分けるのではなく、塊に分けなければなりません。 1000行と現在の文の残りの部分。しかし、以下の実験では、単純化のために2行だけを使用しました。

VIM バッファーで次のテキストを検討してください。

line 1. line 1. line 1.
line 2. line 2. line 2.
line 3. line 3. line 3.
line 4. line 4. line 4.
line 5. line 5. line 5.

実行後:

:2 | exec 'normal! )hvgg' | exec "'<,'>w /tmp/part1.txt" | exec 'normal! gvd'

結果は予想通りです。バッファーには以下が含まれます。

line 2. line 2.
line 3. line 3. line 3.
line 4. line 4. line 4.
line 5. line 5. line 5.

しかし、次の実行後

:2 | exec 'normal! )hvgg' | exec "'<,'>w /tmp/part2.txt" | exec 'normal! gvd'

バッファーには以下が含まれます。

line 2.
line 3. line 3. line 3.
line 4. line 4. line 4.
line 5. line 5. line 5.

ここで何が起こっているのでしょうか?なぜ2行目に移動しないのですかline 3. line 3. line 3.

しかし、次のテキストがバッファに残りたいと思います。

line 3. line 3.
line 4. line 4. line 4.
line 5. line 5. line 5.

答え1

問題の根本はgv最後にあります。視覚的な選択はまだコマンドの前の部分から来るので、これは必要ありません。さらに悪いことは、すでにgvビジュアルモードになっているときに行うため、これは無害ではないということです。現在および以前の視覚領域の交換。前の選択が再び選択されるという意味です!

以前の選択が削除されても、選択は同じ領域または少なくとも残りの領域に適用されます。この場合、line 2.残りの文のうち最初の文になります。

デモンストレーションするには、次のように2回入力すると何が起こるのかを観察してください2G)hvgggvd。これは、ディスクへの書き込みを除いて、100%ノーマルモードコマンドを使用してコマンドラインで行われます。

とにかく私たちはgvそれを失うだけです:

:2 | exec 'normal! )hvgg' | exec "'<,'>w! /tmp/part1.txt" | exec 'normal! d'

それ以外にも、コマンドには整理できるノイズがたくさんあります。 2つとexecそれに応じた引用符は必要ありません。

:2 | exec 'norm! )hvgg' | '<,'>w! /tmp/part1.txt | norm! d

修正する:あなたのコメントのいずれかに応じて...

'<,'>

最初の項目から選択して1行ずつ作業します。ワイヤー最後に選択したビュー領域 - 継続ワイヤー同じ地域の。文字範囲を取得するには、次のようにバックティックを使用する必要があります。

`<,`>

しかし、これはうまくいきません:w。 1行ずつ動作するだけです。

これは、特定のテキストが削除された理由を尋ねる質問の範囲外であることを指摘したいと思います。したがって、ファイルを文字ごとに書くことについて別の質問をすることもできます。

アップデート2:問題に全く異なるアプローチがあります...

次のコマンドを使用してマクロを作成します。

:let @q = ")hs\<CR>\<ESC>k:let @a=@a+1\<CR>:1,.w /tmp/part\<C-R>a.txt\<CR>dgg"
  • 次のコマンドを実行します:let @a = 0
  • 文の上にカーソルを置き、通常モードでマクロを実行します。@q

これは説明したように正しく機能します。文とその上のすべての内容が名前付きファイルに書き込まれ、保存された/tmp/part1.txtテキストは削除されます。さて、別の文に移動して@qもう一度実行してください。今回は同じことが起こりますが、/tmp/part2.txtマクロを実行するたびにファイル名が自動的に増えます。を使用してインデックスをリセットすることができます:let @a = 0

以前のアップデートと同様に、実際の質問に対する答えではありませんが、フレンドリーなので、いくつかの追加のヘルプを提供しています。(OPはまだ私の答えを受け入れていません。)

答え2

ついに許容できる解決策が見つかりました。協力してくれた@B Layerに感謝します(たとえば、コマンドはwファイルに完全な行だけを書くと言われています)。あなたの答えに投票しました。

:let i=1
:1000 | exec 'normal! )hvggd' | exec 'if i<10 | let num="0" . i | else | let num=i | endif' | call writefile(split(@@, "\n", 1), '/tmp/test' . num . '.txt') | let i=i+1

その後、@:最後のブロックが1000行未満の場合は、コマンドの繰り返しを押すとエラーメッセージが表示されます。残りは手動で保存できます。

5回の実行後に予想される結果が得られました。

$ wc -l /tmp/test*.txt
  1001 /tmp/test01.txt
  1000 /tmp/test02.txt
  1001 /tmp/test03.txt
  1006 /tmp/test04.txt
  1001 /tmp/test05.txt

使用したい人のための主な手順を簡単に説明します。

:1000

1000行に移動(ブロック長は1000行以上でなければなりません)

exec 'normal! )hvggd'

次の文の先頭に移動し、1文字の後ろに移動して、次の文の最初の文字が後で削除されないようにします。複数行にわたる文を正しく処理するには、whichwrap=h,lこのオプションを設定する必要があります。私が知っている限り、これはデフォルトではありません。現在のカーソル位置から最初まですべて選択して削除します。削除された内容は登録簿に保存されます。

call writefile(split(@@, "\n", 1), '/tmp/test' . num . '.txt')

レジスタ内容(ブロック)をファイルに書き込む

私の仮定は、99以上のブロックがないということです。さらに必要に応じて、パディング関連部分を必要に応じて調整してください。

関連情報