永続的な行番号をファイルに追加する方法は?


21

このようなテキストファイルがあります(WindowsでgVimを使用)

foo bar baz quux 
corge grault garply 
waldo fred plugh 
[...150 more lines...]
xyzzy thud

ファイルの各行に数字を追加したい。を使用せず:set number、次のように各行の前にテキストとして番号を追加するため、番号はファイルの一部です。

1. foo bar baz quux 
2. corge grault garply 
3. waldo fred plugh 
[...~150 more lines...]
155. xyzzy thud

awkおそらくこの仕事のためのツールです。しかし、私はWindowsを使用しています(ため息)。
-roblogic

すでにここで答え、気にしない:)
roblogic

1
おそらく..またはこれはより一般的ですか?
ムル

それは似ていますが、永続的な行番号が何なのかわかりません。第二に、もう1つの質問は、特にWindows上のgVimのすべての行(およびその答え)です。これは、プレーンvimの1つの段落の単純な番号付きリストです。
ケノーブ

3
まあ、私はその投稿が「永続的な」otを使用していると、バッファが変更されることを示し、数字が純粋に視覚的なものではないことを推測します(あなたと同じ)。Windowsでgvimを指定する理由は、catまたはなどの外部ユーティリティを避けるためnlです。これらのユーティリティは行数を指定できますが、Windowsでは一般に使用できません(OPのコメントからわかるようにawk)。上位2つのソリューションは純粋なVimです。最後に、すべての行と1つのパラは、範囲選択の問題です。明らかに大きな問題ではありません。
ムル

回答:


36

純粋なVimファッションの場合:

:%s/^/\=line('.').". "

説明:

:%s/^/            " the substitution will be applied to the beginning of every line
\=                " the rest of the replacement part is an expression
line('.').". "    " the expression returns the current line number concatenated with a dot and a space

:help \=およびを参照してください:help line()

置換部分で式を使用することは非常に強力であり、FWIWはvimscriptのエントリのかなり良いポイントです。


この非常に便利なコマンドをvimrcのキーマップに追加するにはどうすればよいですか?
cosmicraga

代替のvimヘルプトピックに:help sub-replace-expression
アクセスするには

9

Vimマクロの良い点の1つは、再帰できることです(自分で呼び出すことができます)。

  1. レジスタqをクリアします。 qqq
  2. 最初の行に番号を追加します:(ggI1.スペースを忘れないでください!)
  3. 行の先頭に戻り、マクロの記録を開始します。 0qq
  4. 番号をコピーします。 yW
  5. 行を下に移動して番号を貼り付けます。 +P
  6. 行の先頭に戻り、数値を増やします。 0<c-a>
  7. 行の先頭に戻ります(2桁になってもマクロは壊れません!): 0
  8. 一度マクロを呼び出して、再帰的にします。この時点では、レジスターqにはまだ何もないため、何も起こりません@q
  9. マクロを保存します。 q
  10. マクロをもう一度呼び出して、火花が飛ぶのを見てください!: @@

マクロは、ファイルの最後に到達するまで、それ自体を呼び出し続けます。

再帰的なマクロトリックは、他の多くの同様の問題にも使用できるため、知っておくとよいでしょう。

何らかの理由で再帰的なマクロを使用したくない場合は、手順1と8を省略し、カウントを使用してマクロを複数回100@q実行できqます。たとえば、マクロを100回実行します。


1
強力なもの、私はあなたの習得に屈する。マクロは私にとって黒魔術のようなものです
...-roblogic

1
@ropata、マクロは一連の(ほとんどの)通常モードコマンドのみです。
ロメイン

1
@romainl キーストロークのシーケンスと考える方が良いと思います。
リッチ

2
@ Rich、exコマンドを含む多くのことのシーケンスである可能性があります。
ロメイン

2
@romainlはい、だからこそ、キーストロークと考えるのがベストだと思います。キーボードで入力したとおり(exコマンドを含む)を、まるで手動で入力したかのように再生します。
リッチ

7

このようなタスクを実行するには、vim globalコマンドを使用します。これは、行の先頭に反復を追加するか、テキスト内のシンボルを変更する場合に適用されます。他のソリューションよりも複雑に見えますが、便利な場合はかなり柔軟なパターンを使用でき、あまり考えなくても簡単に変更できます。

最初に、範囲(これを適用する行)を選択します。私は通常マークを使用し(たとえばma、最初の行とmb2番目にありますが、行番号または視覚的な選択を使用することもできます)、次のコマンドの変更を入力します(現在、ユースケースに合わせて調整されています)

:let i=1|'a,'bg/^/s/^/\=i.". "/|let i=i+1

脱構築

:let i=1

これiにより、変数に開始値が設定されます。通常、リストは1で始まるため、iを1に設定しています。

|

バーは新しいコマンドを開始します

'a,'b

これにより、次のコマンドの範囲が設定されます。リストの最初の行と最後の行に設定されるamark からmarkに移動しbます。

g/^/

これはグローバルコマンドです。ファイル(または範囲)で特定の正規表現を検索し、一致した各行でコマンドラインの残りを実行します。「行頭」を検索して、すべての行を照合しています。次のようなテキストがある場合

Item some txt
other text

Item second item
whatever
Item third

そして、これらのラベルをItem他の行の前に置き、他の行を無視したい、do g/Item/またはg/^Item/代わりに(リテラルのItemテキストを仮定して)

s/^/\=i.". "/

これにより、正規表現が実行され、行の先頭がia で連結された値に置き換えられ.ます。通常、これは何でもできます(Itemたとえば、ラベルを番号に置き換えます)。

|let i=i+1

バーは新しいコマンドを開始しますが、グローバルが完了した後ではなく、グローバルコマンド内で実行する2番目のコマンドを設定します。その結果i、次の行がgによって処理される前にインクリメントされます。柔軟性の別の場所があります。iの変更は何でもかまいません(2ずつインクリメントし、フィボナッチ数列の次の要素を生成する関数を呼び出します)。


7

すべての行に番号を追加します

すべての行に行番号を追加する:%!nl -baor :%!cat -nコマンドを使用できます。

Windowsでは、Cygwin / MSYS / SUAをインストールする必要があります。

選択した行に番号を追加します

選択した行にのみ番号を追加するには、ビジュアルモード(vおよびカーソル)で番号を選択し、完了したらコマンドを実行します:(:%!nl空白行を無視)または:%!cat -n(空白行を含む)。

書式設定

余分なスペースを削除するには、ビジュアルブロック(Ctrl+ v)でそれらを選択し、削除します(x)。

一部の文字を追加する(するには.:))数字の後に、視覚的なブロック(でそれらを選択Ctrl+ v)、そして文字追加(A、で終了し、その後、文字を入力Esc)。


2
これは質問で与えられたのと同じフォーマットを与えません。ただし、ソリューションのシンプルさが気に入っています。
カールYngveLervåg15年

@KarlYngveLervågありがとう、答えにそれを含めました。
ケノーブ

5

romainlの答えの修正:

:%s/^\(\d\+\. \)\?/\=line('.').". "

これは単に行番号を追加するだけでなく、既存の行番号を既存の行番号と置き換えます。途中で線を挿入した場合、期待どおりにすべての番号が付け直されます。

これは、任意の数字の後に。行の先頭に新しい番号が付いたスペース。すでにこのパターンで始まる行がある場合、これは明らかに壊れるので、よく考えて使用してください。

追加された部分:

  • ^ -行頭
  • \( -新しいサブグループを開始
  • \d\+ -数字を1回以上一致させる
  • \. -ドット(.)とスペースを一致させます
  • \) -サブグループの終了
  • \? -グループをオプションにし、この行にまだ番号がない場合に以前のように機能するようにします。

ボーナスヒント:行番号
削除するには、repalceパーツを空にして同じパターンを使用できます。

:%s/^\(\d\+\. \)\?//

5
I1. <esc>^qqyWjP^<C-a>q

これにより、最初の2行に番号が付けられ、を押し@qて後続の行に番号を付けることができます(または、18@q合計20行に番号を付ける場合はexと入力します)。

説明:

I1. <esc>  Number the first line
hqq        Go back to the start of the line and start recording a macro
yWjP       Copy the line number to the next line
^<C-a>     Increment the next line's line number
q          Finish recording

この利点は、外部コマンドを必要としないことです。これは、たとえばWindowsでVimを使用している場合に便利です。


入力後1. <esc>h、最初の列ではなく、2番目の列にいます。私が代わるh0私はあなたのソリューションは非常に良いことだと思いますた後、。
カールYngveLervåg15年

@KarlYngveLervågおっと、それはタイプミスでした。ありがとう、修正しました。
ドアノブ

問題ない。ただし、説明はまだ更新されていません。また、多くのキーボードでは、^などの組み合わせを入力できるようにするために2番目の文字を待ちます^a -> â。私は今でもその最善の解決策に同意していますが、これについても言及すべきだと思います。
カールYngveLervåg15年

3

私が選んだ答えは最高だと思いますが、多様性の精神で、外部プログラムを使用した代替案を提供します

:%!cat -n

これにより、(で示される%)バッファ全体が外部プログラムを通してフィルタリングされますcat。ここで、-nフラグは入力の各行に行番号を付加します。

もちろん、これにはcatインストールが必要です。これは(おそらく)すべてのUnixライクなシステムに当てはまります。

チェックアウト:help :range!外部プログラムを通じてフィルタリングの詳細については。


1
質問者はWindowsでgVimを使用しているため、このソリューションはおそらく動作しません。しかし、他の人がそこから学ぶ機会をまだ提供していると思います。
-tommcdo

インストールmsysgitしてPATHに追加した場合(IIRCはインストールオプションです)、このソリューションはWindowsでも動作するはずです。
マーティントゥルノイ

4
cat -nはPOSIXではありませんnlが、そうであるため、より良いオプションかもしれません。
ムル

2

少しハック的な解決策は次のようになります(<と>の間に書かれたものはすべて、Ctrl+ を押した後に挿入されますv):

:%normal :redir @"<Enter>:-=<Enter>:redir END<Enter>I<C-R>".<Tab><Esc>kdd

脱構築

:%normal {commands}

範囲で指定された各行、この場合はすべての行で通常モードのコマンドを実行します

:redir @"

exコマンドによって作成されたすべての出力を名前のないバッファーにリダイレクトします。

:.=

現在の行番号を出力するexコマンドです(残念ながら先行する改行を使用)

:redir END

名前のないバッファへのリダイレクトを停止します

I<C-R>".<Tab><Esc>

名前のないバッファのコンテンツをで挿入します。そして各行の前にタブがあり、挿入モードを終了します。

kdd

1行上に移動し、:。=コマンドの結果である改行を削除します。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.