選択範囲または一致の各行に増分番号を挿入します


10

解決するための2つの一般的なアプローチについて考えることができる問題がありますが、どちらのアプローチの詳細かわかりません。

...
Level 1:    cũng    also
Level 1:    và      and
Level 1:    như     like; such as
Level 2:    các     plural marker
Level 2:    của     belonging to
...

「レベルn」で始まる各行に、「01」で始まる番号を挿入します。簡単にするために、数字を前に付けましょう。

アプローチ1:同じレベルのすべてのラインを手動で選択します。魔法を呼び出す私はすぐに学びます。

アプローチ2:すべての行が指定されたレベルに一致する検索と置換を記述します。これには、一致ごとに置換テキストに番号が含まれ、一致ごとに1ずつ増加します。

StackOverflowや他のVimサイトで同様の質問見つけましたが、それぞれに次の問題が1つ以上あるようです。

  1. 任意の増加する番号ではなく、現在の行番号を挿入することです。
  2. 数字のゼロ詰めは行いません。
  3. Windows 7で実行しているVim 7.4の選択では実際には機能しません(これらはエラーになりE481: No range allowedます)。

Windowsでmswin.vimを使用してgVimを実行していますが、セットアップをカスタマイズする必要なく、すべてのバニラVimインストールで機能するソリューションが最適です。


質問のために私が考えることができる最高のタグは存在しません:選択範囲なので、タグを付け直すか、これらのタグの1つを作成してください。
ヒッピートレイル2015

1
このプラグインは問題の完全な解決策ではありませんが、数値の列を追加する場合に非常に役立ちます:VisIncr。ドキュメントはこちら。FWIW。
lcd047 2015

回答:


17

https://vi.stackexchange.com/a/818/227での回答と同様に、グローバルコマンドを使用できます。

これを使用すると、パターンに一致する行を検索し、そのコマンドを実行するようにvimに指示できます。

あなたのケースでは、「レベルN:」で始まる行にテキストを付加したいので、グローバルコマンドは次のようになります。

:g/^Level \d:/{COMMANDS}

コマンドの代替コマンド(正規表現置換)の使用

コマンドはもっと楽しいです。変数は使いやすいので、私は通常、このようなものの正規表現の置換を行うのが好きです。

あなたの質問の例

:let i = 1 | g/^Level \d:/s/^/\=printf("%02d ", i)/ | let i = i+1

使い方

置換コマンドの置換セクションでは、式を使用できます。

最初に、変数iを開始番号に設定します。1を選択しましたが、いくつでもかまいません。let i = 1

次に、一致した行でアクションを実行するように設定するグローバルコマンドを実行します。 g/^Level \d:/

グローバルコマンドで値を挿入し、substitutionコマンドとletコマンドを使用してカウンターをインクリメントします。 s/^/\=printf("%02d ", i)/ | let i = i+1

置換コマンドの正規表現は、行の先頭を見つけて^それを式に置き換えます。この式は、フォーマットされた印刷の結果になります。C言語と同様に、vimのprintfはフォーマットパラメータを受け取ります。%02dは、引数を10進数のように変換し、d少なくとも2つのスペース2を使用し、0を埋め込むことを意味します0。詳細およびその他の変換オプション(浮動小数点フォーマットを含む)については、を参照してください:help printf。printfにカウント変数iを渡し01、1回目、022回目などを与えます。これは、置換コマンドで使用されて、行の先頭を置き換え、printfの結果を先頭に効果的に挿入します。

d:の後にスペースを置いていることに注意してください"%02d "。あなたは質問でそれを要求しませんでした(そして私は出力例を見ませんでした)が、私はあなたが「レベル」という単語から数を分離したいと思ったのではないかと思いました。レベルのLのすぐ隣に数値を挿入するには、printfに指定された文字列からスペースを削除します。

最後に、それはlet i = i + 1各置換の後にカウンターをインクリメントします。

これは一般に、他の基準と一致する行の一部を任意の機能データで置き換える場合に適用できます。

通常のコマンドを組み合わせて使用​​する

これは、単純な挿入や複雑な編集に適しています。置換の場合と同様に、マッチングにはグローバルを使用しますが、正規表現の代わりに、ユーザーが入力したかのように一連の操作を実行します。

あなたの質問の例

:let i = 1 | g/^Level \d:/execute "normal! I" . printf("%02d ", i) | let i = i+1

使い方

使用される値は置換に非常に似ています(私たちはまだprintfを使用して、2桁で0が埋め込まれるように数値をフォーマットしています)が、操作は異なります。

ここでは、文字列を受け取り、exコマンド(:help :exe)として文字列を実行する実行コマンドを使用します。「normal!I」とデータを組み合わせた文字列を作成します。最初は「normal!I01」、2回目は「normal!I02」となります。

このnormalコマンドは、通常モードと同じように操作を実行します。この例では、通常のコマンドはIで、行の先頭に挿入されます。使用ddした場合、行を削除しo、一致した行の後に新しい行を開きます。これはI、通常モードで自分で入力した(または他の操作を行った)場合と同じです。!after を使用して、normalマッピングが邪魔にならないようにします。を参照してください:help :normal

次に挿入されるのは、代用を使用する最初の例と同様に、printfの値です。

execute "normal! ^2wy" . i . "th$p"テキストの先頭に^移動し、2ワード前に移動し2w、i番目の 'h'文字までヤンクしy" . i . "th、行の最後に移動し$、を貼り付けることができるため、この方法は正規表現よりも洗練されている場合がありますp

これは、マクロの実行とほとんど同じですが、実際にはレジスターを使い果たしておらず、任意の式の文字列を組み合わせることができます。これは非常に強力だと思います。

各レベルに独自のカウンターがあるアプローチ

各レベルで独自のカウンターを取得する必要がある場合があります。事前にレベルの最大数がわかっている場合は、次の操作を実行できます(最大レベルを見つけるために追加のコードを追加することはそれほど難しくはないかもしれませんが、この回答は長くなりすぎます。これは実際に長くなっています)。

まず、すでに整数として使用している場合に備えて、iを解放します。iをリストに変換することはできません。そのように作成する必要があります。

:unlet! i

次に、レベル数を含むリストをiに設定します。あなたはあなたの質問に2を示しましたが、それを楽しむために10と仮定しましょう。リストのインデックス付けは0ベースであり、リストのように1ベースを修正する手間をかけたくないので、十分な数の要素(11)を作成し、0インデックスは使用しません。

:let j = 0
:let i = []
:while j < 11 | let i += [1] | let j += 1 | endwhile

次に、レベル番号を取得する方法が必要です。幸いなことに、関数としても代替を使用できるので、それに行を追加してレベル番号を抽出しますsubstitute(getline("."), "^Level \\(\\d\\):.*", "\\=submatch(1)", "")

これでiは11 1のリストになっているため(各インデックスはレベルのカウンターです)、上記の例のいずれかを調整して、この置換の結果を使用できます。

代替コマンドを使用:

:unlet! i | unlet! j | let j = 0 | let i = [] | while j < 11 | let i += [1] | let j += 1 | endwhile
:g/^Level \d:/let ind=str2nr(substitute(getline("."), "^Level \\(\\d\\):.*", "\\=submatch(1)", "")) | s/^/\=printf("%02d ", i[ind])/ | let i[ind] += 1

通常のコマンドで:

:unlet! i | unlet! j | let j = 0 | let i = [] | while j < 11 | let i += [1] | let j += 1 | endwhile
:g/^Level \d:/let ind=str2nr(substitute(getline("."), "^Level \\(\\d\\):.*", "\\=submatch(1)", "")) | execute "normal! I" . printf("%02d ", i[ind]) | let i[ind] += 1

入力例:

Level 1: stuff

Level 1: Stuff

Some text
Level 3: Other

Level 1: Meh

Level 2: More

出力例:

01 Level 1: stuff

02 Level 1: Stuff

Some text
01 Level 3: Other

03 Level 1: Meh

01 Level 2: More

うわー、非常に百科事典。私は最初の部分だけを読んだだけで、ここ数年よりもそれだけでVimについて多くを学んだような気がします。これは、Stack Exchangeを平均的なQ&Aサイトよりも優れたものにする種類の回答であり、Vim固有のSEを持つことの利点も示しています。
ヒッピートレイル2015

3

https://stackoverflow.com/a/4224454/15934からビルドして、数値をゼロで埋めることができます。

" A reminder: how to start numbers at the first line
:'<,'>s/^\s*\zs/\=(line('.') - line("'<")+1).'. '

しかし、数字のパディングのアクションを簡略化するために、私は関数とコマンドのペアに行きます:

command!  -range=% -nargs=? PrependNumbers <line1>,<line2>call s:Prepend(<args>)

function! s:ReplExpr(nb_digits, number)
  return repeat('0', a:nb_digits - strlen(a:number)).a:number
endfunction

function! s:Prepend(...) range
  let pattern = a:0 > 0 ? '\ze'. a:1 : '^'
  let nb_values = (a:lastline - a:firstline) + 1
  let nb_digits = strlen(nb_values)
  exe ':'.a:firstline.','a:lastline.'s#'.pattern.'#\=s:ReplExpr(nb_digits, 1+ line(".")-'.a:firstline.')." "#'
endfunction

次に、行を選択して入力します:PrependNumber(が表示されます:'<,'>PrependNumber。[注:このコマンドはオプションのパラメーターを受け取ります。その前に数字が挿入されるパターン]


しかしline(".")、「現在の行番号を使用する」という意味ではありませんか?それは私の問題だった1.私は見つけることができる前の答え。
ヒッピートレイル2015

1
はい、そうです。そのため、範囲の最初の行の行番号を差し引きます。
Luc Hermitte、2015

Vimでスクリプトを入力する方法さえ覚えていないので、まだテストしていません。最初に読み上げます(-:
hippietrail

1
ウィンドウの下で、コードをコピーしてに貼り付けます$HOME/vimfiles/plugin/whatevernameyouwish.vim。または、$HOME/_vimrc(初めて)Windowsのファイル名を使用することもできます。マシンの$ HOMEが何かわからない場合は、vimにそれが何であるかを尋ねてください->:echo $HOME
Luc Hermitte

1
:sourcevimスクリプトが適切なディレクトリ({rtp} / plugin、またはファイルタイプ固有のプラグインの場合は{rtp} / ftplugin / {filetype} / ftplugin)に正しくインストールされている場合でも、必要はありません。:source10年以上前に私たちがプレーしなければならなかったものです。
Luc Hermitte、2015

2

マクロを記録することでそれに近づくことができます。元のファイルから始めて、最初のインスタンスに番号を付加します。

01 Level 1:    cũng    also
Level 1:    và      and
Level 1:    như     like; such as
Level 2:    các     plural marker
Level 2:    của     belonging to

にカーソルを移動し01、で選択してヤンクしyiwます。次に、この時点からの行動を記録します。

qq/^Level 1<CR>P<C-A>A<space><esc>0yiwq

  • qq レジスタqでマクロを開始する
  • /^Level 1<CR> 「レベル1」で始まる行を検索します
  • P カーソルの前に貼り付け(あなたの番号が含まれています)
  • <C-A> 数を増やします
  • A<space><esc> 番号の後にスペースを挿入します
  • 0 最初に移動
  • yiw 現在の番号をヤンクする
  • q マクロを終了する

次に、を使用してこのマクロを繰り返し@qます。


1
ある<C-A>コントロール+?これにより、Windows上のVimのすべてが選択されます。
ヒッピートレイル2015

Control + aです。vimの場合は、数値を増やします。VimアクションではなくWindowsアクションを実行するようにキーバインディングを変更した場合、人々がここに投稿するほとんどのことを実行できなくなります。
jecxjo 2015

誰かの無限の知恵のため、WindowsのVimバージョンには異なるバインディングが付属していません。私はバニラのすぐに使えるバインディングを使用しています。20年以上Vimのキーバインドを変更したことがないので、思い出せます(-:
hippietrail

そうではないはずですが、私のWindowsインストールには通常のvimバインディングがあります。他の誰かのビルドのvimをインストールした可能性はありますか?それとも、「簡単」モードでvimを実行できますか?Windowsは、通常の簡単なモードオプションでデスクトップアイコンをインストールすると思います。
jecxjo 2015

3
いいえ、Windowsのデフォルトのインストールでmswin.vimがロードされるためです。独自のvimrcを作成し、mswin.vimをロードしない場合、通常のvimバインディングが取得されます。私はすべてのインストール(Linux、Mac、Windows)で単一のvimrcを保持しており、mswin.vimを扱いません。この問題の詳細については、stackoverflow.com
questions / 289681 /…
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.