Vimのレジスタ一覧(:registers)と名前付きレジスタの使い方
ヤンクした文字列を貼り付けようとしたら、さっき消したはずの別の行が出てきて困りました。Vimを使い始めた頃、こういう場面に何度も遭遇しました。原因は単純で、yもdも同じ無名レジスタを使い回すからです。レジスタの仕組みを知らないと、コピーと削除が同じ場所を奪い合っていることに気づけません。行や文字や矩形でのコピーの取り方は別にまとめてあるので、レジスタの話はその先だと考えてください。
この記事では、Vimのレジスタが全部で何種類あるかを整理したうえで、実務で意識する必要があるものと、名前だけ知っておけば十分なものを分けて説明します。自分で使い分ける名前付きレジスタ("a〜"z)は、大文字で追記して散らばった行を集める使い方まで踏み込みます。
検証環境:macOS + Vim 9.1.1752 / Neovim 0.12.4。レジスタの分類は両者の:help registersを突き合わせ、:registersの出力は実際に操作してから取得したものです。
目次(8項目)
| キー | これだけ覚える |
|---|---|
"" | 無名レジスタ。ヤンク・削除が自動的に上書きする |
"0 | 直近ヤンク専用。削除しても消えない |
"a〜"z | 自分で使い分ける保管庫。書き込むたびに上書き |
"A〜"Z | 同じ保管庫の後ろに追記 |
"_ | ブラックホール。書き込んだ内容を破棄する |
レジスタの全体像
Vimの公式ヘルプ(:help registers)は、レジスタを10種類に分類しています。数として数えると合計48個です。:registers(省略形は:reg)を実行すると、今どのレジスタに何が入っているかを一覧で確認できます。
There are ten types of registers
| 種類 | 記法 | 個数 | 役割 |
|---|---|---|---|
| 無名レジスタ | "" | 1 | 直近のヤンク・削除・変更が自動的に入る |
| 番号付きレジスタ | "0 〜 "9 | 10 | ヤンク・削除の履歴 |
| 小削除レジスタ | "- | 1 | 1行未満の削除が入る |
| 名前付きレジスタ | "a 〜 "z | 26 | 自分で使い分ける汎用スロット |
| 読み取り専用レジスタ | ": ". "% | 3 | 直近のコマンド・挿入文字列・ファイル名 |
| 代替バッファレジスタ | "# | 1 | 直前に開いていたファイル名 |
| 式レジスタ | "= | 1 | Vim script式の評価結果を挿入 |
| 選択・ドロップレジスタ | "* "+ "~ | 3 | OSのクリップボードとドラッグ&ドロップ |
| ブラックホールレジスタ | "_ | 1 | 書き込んだ内容を破棄する |
| 検索パターンレジスタ | "/ | 1 | 直近の検索パターンが入る |
読み取り専用レジスタと代替バッファレジスタ("#)は役割が近いので同じ枠で語られがちですが、公式の分類では別の種類として並んでいます。48という数字はこの表の個数を足したものです。
Neovimでは47個になる
Neovimのヘルプでも同じく10種類に分かれていますが、8番目の項目が「The selection registers "* and "+」となっていて、ドロップレジスタ"~がありません。GUIへのドラッグ&ドロップで使うレジスタで、Neovimは対応していないためです。したがって数え方を揃えるとVimとNeovimで1個ずれます。
| Vim | Neovim | |
|---|---|---|
| 種類 | 10種類 | 10種類 |
| 個数 | 48個 | 47個("~が無い) |
48個と聞くと多く感じますが、日常的に触るのは無名・番号付き・名前付き・ブラックホールの4つくらいで、残りは「そういうものがある」と知っておけば困ったときに調べれば十分です。
:registersの読み方
手元のVim 9.1で、4行のバッファに対してyy(1行ヤンク)→dd(1行削除)→x(1文字削除)を順に実行してから:registersを叩くと、次のようになりました。
Type Name Content
c "" d
l "0 alpha^J
l "1 bravo^J
c "a named-a
c "- d
この5行に、レジスタの仕組みがほぼ全部出ています。最後に実行したxの結果(dという1文字)が無名レジスタに入り、ヤンクしたalphaは"0に、行削除したbravoは"1に、1文字だけの削除は小削除レジスタ"-に、それぞれ分かれて残っています。
左端のType列も見落とされがちですが重要です。lは行単位(linewise)、cは文字単位(charwise)を表し、これがpの貼り付け方を決めます。行単位なら現在行の下に新しい行として入り、文字単位ならカーソルの直後に挿入されます。内容の末尾にある^Jは改行文字の表示で、行単位でヤンクされたことの現れです。
:registers。"" "0 "1 "- が別々に埋まっている無名レジスタが上書きされる仕組み
冒頭の失敗は、無名レジスタ"の仕様を知らないままpを使ったことが原因でした。yでヤンクしてもdで削除しても、指定したレジスタが無ければ結果は無名レジスタに入ります。つまりヤンクした直後に何かを削除すると、無名レジスタの中身は削除したほうの文字列に置き換わります。pで貼り付けたときに「さっきコピーしたものと違う」と感じたら、まずこれが原因になっている可能性があります。
さらに紛らわしいのが、"ayyのように名前付きレジスタを明示的に指定した場合でも、Vimはその内容を無名レジスタにもコピーする点です。名前付きレジスタは独立した保管場所だと思い込んでいると、直後のpで予想外の文字列が出てきて驚くことになります。
番号付きレジスタで削除の履歴をたどる
"1から"9は削除の履歴で、消したものが何に入るかは削除の大きさで決まります。
| 削除した操作 | 入る先 |
|---|---|
| dd/dap(1行以上) | "1。既存の中身は"2→"9へ押し出される |
| x/行内のdw(1行未満) | "-(小削除レジスタ) |
何行か前に消した文字列を戻したいときは、"3pのように番号を変えながら試すとたどり着けます。
もう一つ覚えておくと便利なのが"0です。これはヤンクだけを記録する専用のレジスタで、削除の影響を受けません。
const a = 1;
│ ← 直前にddで1行削除した
const a = 1;
const a = 1;
ヤンクした行の後で別の行を削除しても、無名レジスタは削除内容で上書きされる一方"0はヤンクした内容を保持し続けます。ヤンクしてから編集作業を挟むことが多い人は、pより"0pを使う癖をつけたほうが事故が減ります。番号付きレジスタの割り当てには細かい例外もあります。番号付きレジスタの仕組みで詳しく扱っています。
名前付きレジスタ"a〜"zを使い分ける
番号付きレジスタは削除のたびに中身が押し出されていきますが、"a〜"zの26個はVimが勝手に書き換えません。"ayyのように自分で名前を指定したときだけ中身が入るので、残しておきたいものを置く場所として使えます。26個を1つの作業で使い切ることはまずないので、「aは移動先の関数名」「bは消す予定のコメント」のように用途ごとに割り当てておくと、無名レジスタの上書きに振り回されずに済みます。
同じ名前を小文字で指定すると上書き、大文字で指定すると追記になります。"ayyを2回実行すれば2回目の行だけが残りますが、"Ayyなら実行するたびにaの後ろへ行が積み重なっていきます。追記したときも無名レジスタには写るので、直後のpでは積み上げたあとの全体が貼り付けられます。
大文字で追記して散らばった行を集める
ファイルのあちこちにある行を1か所にまとめたいとき、無名レジスタだけだと「1行ヤンクして移動して貼る」を往復するしかありません。検索で次のマッチへ飛びながら"Ayyを繰り返せば、1つのレジスタに集めてから一度に貼り付けられます。
/TODO<Enter>
"ayy " 1件目は小文字で入れて、前の中身を捨てる
n"Ayy " 次のTODOへ移動して追記
n"Ayy " さらに次のTODOへ移動して追記
G"ap " ファイル末尾に集めた内容を貼り付け
TODO: fix a
TODO: fix b
│ ← 2行を"ayyと"Ayyで集めた直後
TODO: fix a TODO: fix b TODO: fix a TODO: fix b
1件目だけ小文字にしているのは、前の作業でaに入れたものが残っていると、その後ろに積まれてしまうからです。慣れないうちは小文字と大文字を押し間違えて、集めたものを上書きすることもあります。途中で:registers aを叩いて、何行たまったかを確かめながら進めると安心です。レジスタはバッファをまたいで残るので、複数のファイルを切り替えながら"Ayyを続けても全部が1つに積み上がります。集め終わったら:newで空のバッファを開いて"apで貼り、:w todo.mdのように保存すれば1つのファイルにまとまります。
行単位と文字単位で区切りが変わる
yyのような行単位のヤンクを追記すると、それぞれが1行として改行で区切られて積み重なります。ylのような文字単位のヤンク同士を追記した場合は、改行なしでそのまま連結されます。手元のVim 9.1とNeovim 0.12で、"bylのあと別の行で"Bylを実行すると"bはTTになりました。文字単位で入っているレジスタに行単位のヤンクを追記すると、レジスタ全体が行単位に変わり、最初の文字列も1行として扱われます。
ただし'cpoptions'に>のフラグが入っていると、文字単位でも追記の前に改行が挟まります。vim -u NONEで起動したときのようにVi互換モードになっているとこのフラグが立つので、連結されるはずが改行で分かれたときは:set cpoptions?を確認してください。
条件で集めるなら :g と組み合わせる
集める条件が「この文字列を含む行」のように機械的に書けるなら、1件ずつ拾うよりグローバルコマンドのほうが確実です。:gから実行する:yankにも大文字のレジスタ名を渡せます。
:call setreg('a', [], 'l') " a を空の行単位レジスタにする
:g/TODO/y A " TODO を含む行を全部 a に集める
先に空にするとき、:let @a = ''だとaは文字単位の空文字列になります。そこへ行単位で追記すると、さきほどの規則どおり全体が行単位に変わり、空文字列が1行ぶんとして残るため、貼り付けた先頭に空行が1つ入ります。実機ではVimでもNeovimでも同じ結果でした。setreg()の第3引数に'l'を渡して行単位の空レジスタにしておけば、この空行は出ません。手で拾うのが向くのは、目で見て選ぶ必要があるときだけです。
マクロも同じレジスタに入る
名前付きレジスタで見落としやすいのが、マクロの記録先も同じ"a〜"zだという点です。qaでマクロを記録すると、それまでaに集めていた行は記録したキー操作で上書きされて消えます。逆にqAは既存のマクロの後ろにキー操作を追記する操作になり、テキストの追記と同じ規則で動きます。
収集の手順そのものをマクロにして連打したいときは、記録先と集める先を分けます。たとえばqqで記録を始め、/TODOで次へ移動して"Ayyを実行し、qで止めます。あとは@qを繰り返せば、行はaに、手順はqに分かれてたまります。両方をaにすると、記録を止めた時点でaはキー操作だけになり、記録中に集めた1件目は残りません。さらに@aを1回実行すると、マクロの中身の後ろに集めた行がつながります。手元で試すと、:echo @aで見て/TODO^M"Ayy^@TODO three^@のような中身になり(:registersでは改行が^Jと表示されます)、次の@aではこの行の文字までキー操作として打ち込まれました。
:registers を見たところブラックホールレジスタで削除を「無かったこと」にする
コピーした文字列を別の行に貼り付けたいだけなのに、貼り付け先の行をddで消すとレジスタの中身が上書きされてしまいます。こういうときに使うのがブラックホールレジスタ"_です。"_ddのように指定すると、削除した内容はどこにも保存されずに消えます。
"ayy " a レジスタに現在行をヤンク
/target
"_dd " 削除するが a も無名レジスタも汚さない
"ap " さっきヤンクした内容を貼り付け
置換系のマッピングを自作するときにも、この"_を経由させると「置換したらクリップボードの中身が消えた」という事故を防げます。
複数箇所に同じ文字列を貼り付ける作業をしていて、途中の削除操作で無名レジスタの中身が消し飛んだことが何度もありました。それに気づいてからは、使い回すヤンク内容は"ayyのように名前付きレジスタへ意識的に逃がすようにしています。地味ですが、これだけでコピペ関連のやり直しはかなり減りました。
クリップボード連携のレジスタは環境差に注意
"*と"+はOSのクリップボードと連動するレジスタで、Vimとターミナルの外にあるアプリの間でコピー&ペーストをしたいときに使います。ただし、これは+clipboard機能付きでビルドされたVim(多くのLinuxディストリビューションのvim-gtk系や、macOS/WindowsのGUI版)でないと機能しません。:echo has('clipboard')で0が返る環境では"*yとしても何も起きないので、まず確認しておくと安心です。WSL環境やSSH越しの作業では、この確認を飛ばしてハマる人をよく見かけます。残りのレジスタは必要になったときに:h registersを引けば十分です。
まとめ
Vimのレジスタは48個ありますが、全部を覚える必要はありません。無名レジスタが上書きされる仕組みと、"0・名前付きレジスタ・ブラックホールレジスタの使い分けさえ押さえておけば、コピペ関連のトラブルはほとんど防げます。散らばった行を集めるときは1件目を小文字、2件目から大文字にし、マクロの記録先とは別のレジスタを使ってください。まずは:registersで今のレジスタの中身を眺めてみるところから始めるとよいでしょう。貼り付け側の記法はモードによって変わるので、コピー&ペーストの記事にある貼り付け方もあわせて確認しておくと安心です。
ここで扱ったキーは、ブラウザ上で動くVim道場のコピー先を使い分けるでそのまま試せます。インストールもログインも要りません。