TT Lab
はじめる
学ぶ 学習パス コース

vimとtmux

範囲 + 動作、そして繰り返しの三段階

TT Labで続きを見る

一言でいうと

exコマンドはすべて、範囲 + 動作の構造です。そして、繰り返しには3段階があります。.(最後の編集の繰り返し)、置換(パターンが規則的なとき)、マクロ(手順が必要なとき)です。

なぜ必要なのか

ログファイルから特定の条件の行だけを残し、IPをマスキングし、カラムを1つ削除する必要があります。sedとawkでパイプラインを組むこともできます。しかし、結果を目で見ながら、1段階ずつ確認して元に戻せるという点で、エディターの中でやるほうがよいことが多いです。特に、正解がわからないまま探りながら整える作業がそうです。

問題は、ほとんどの人がvimを「1文字ずつ直すツール」としてしか使わないことです。500行に同じ修正をする必要があるとき、手で500回やるか、vimを諦めてほかのツールを探します。その間にある層が、置換とマクロです。

どう動くのか

まず、exコマンドの構造から揃えます。

範囲 意味
:5 5行目
:5,10 5–10行目
:% ファイル全体(= 1,$)
:. 現在の行
:'<,'> Visualで選択した領域

ここに動作が付きます。s/찾을것/바꿀것/플래그(韓国語の語は、順に「探すもの」「置き換えるもの」「フラグ」を意味します)が置換で、g/패턴/명령(韓国語の語は、順に「パターン」「コマンド」を意味します)が「パターンに一致する行ごとにコマンドを実行する」です。

必ず知っておくべき3つの落とし穴です。

  1. gフラグを外すと、行ごとに最初のマッチだけが置換されます。:%s/old/new/と:%s/old/new/gは、別のコマンドです。
  2. :gと:vは反対です。:g/ERROR/dはERRORを含む行を削除し、:v/ERROR/dはERRORがない行を削除します。ログから必要なものだけを残すときは:vです。
  3. 後方参照を使うと、マッチの一部だけを残せます。括弧で囲んだ部分を\1、\2で呼び戻します。マッチ全体は&です。

マクロの正体は、思っているより単純です。qaで記録を開始してキーを押し、qで終えると、そのキー入力が文字列そのままレジスターaに保存されます。yankとマクロが同じa–zの領域を使うのも、そのためです。@aは、その文字列をもう一度入力するだけです。

この事実を知っていると、2つのことが導かれます。マクロを:reg aで覗くことができ、"apで取り出して編集したあと、"ayyで再び保存することもできます。ラボでマクロをファイルに保存して提出するのも、同じ原理です。

繰り返し可能なマクロの設計原則が3つあります。これを知らないと、マクロが2行目でずれます。

  1. 開始点を絶対的に固定します。マクロの最初のキーを0(行頭)にしておけば、カーソルがどこにあっても同じ場所から始まります。
  2. 移動は相対的に行います。f,(次のカンマへ)のように、内容を基準に動かすと、行ごとに長さが違っても動作します。
  3. 最後に次の対象へ移ります。jで次の行に下りておけば、10@aで繰り返せます。

大文字のレジスターは追記です。:g/prod/y Aは、prodを含むすべての行をレジスターaに順番に積み重ねます。小文字のaで書くと毎回上書きされて、最後の行だけが残ります。散らばった行を1か所に集める慣用句が、ここから生まれます。

現場での姿

個人情報のマスキング。ログを共有する必要があるのに、IPの最後のオクテットは消さなければなりません。後方参照の置換1行で、ファイル全体が整理されます。

設定ファイルの一括コメントアウト。ステージングの項目だけを一時的にオフにしたいときは、:g/staging/normal I# 1行で済みます。:normalは各行でNormalモードのキーを実行するという意味なので、行フィルターとマクロを結合する橋渡しの役割をします。

マッチの個数だけを数える。:%s/패턴//gn(韓国語の語は「パターン」という意味です)は、何も変更せず「N個のマッチ、M行」だけを教えてくれます。置換する前に、影響範囲を確認する安全装置です。

繰り返しをなくす3つの手

vimで速さを生み出すのは、ショートカットの数ではなく、同じ編集を繰り返さない方法です。3つだけ手に馴染ませれば、ほとんどが片付きます。

.は、最後の変更を繰り返します。そのため、編集を繰り返し可能な1つのまとまりにする習慣が重要です。ciw새이름<Esc>(韓国語の語は「新しい名前」という意味です)のように1回で終わる形に直しておけば、次の位置ではn.だけを押せばよいです。

/oldName<CR>      찾는다
ciwnewName<Esc>   첫 자리를 고친다
n.                다음 자리로 가서 같은 것을 반복

一致する場所を目で見ながら選べるので、すべてを置換してはいけない場合は:%sよりもよいです。

置換は、範囲と確認が核心です。

:%s/\vold_(\w+)/new_\1/gc

\vは、正規表現をほかの言語に近い形にして、バックスラッシュを減らしてくれます。cは、場所ごとに確認を求めます。範囲は%(全体)以外にも、:'<,'>(選択領域)、:.,+10(現在の行から10行)、:g/pattern/s/.../.../(条件に合う行だけ)で絞り込みます。

:gは、置換よりも幅広く使います。「パターンに一致する行でコマンドを実行する」ものなので、削除、移動、収集がすべてできます。

:g/^\s*#/d          주석 줄을 전부 지운다
:g/TODO/t$          TODO 줄을 파일 끝에 모은다
:v/error/d          error 가 없는 줄을 지운다(v 는 g 의 반대)

マクロは、.ではできない複数の段階を収めます。qaで録画を開始し、1行でやることをすべてやってから、qで止めます。@aで1回、100@aで100回実行します。

最後まで安全に回すコツがあります。マクロの最後にj0を入れて、次の行の行頭に移動させると、位置がずれません。そして処理する行がなくなったらマクロが失敗するようにしておけば、100@aを押しても、ファイルの末尾で自然に止まります。/pattern<CR>をマクロの中に入れるのが、その役割を果たします。

元に戻す操作は、ツリーです。誤ってマクロを100回実行してしまったら、uを100回押す代わりに、:earlier 1mで1分前の状態に戻ります。:undolistで分岐を見て、:undo <번호>(プレースホルダーは番号です)で特定の状態に移動することもできます。

次のラボですること

2つのラボが続きます。まずvim-powerで、ログファイルを対象に、検索・置換・行フィルターをexスクリプトとして作って提出し、続くvim-macrosでは、マクロをファイルに保存して、採点ツールがレジスターに入れて実行してみるようにします。ESC文字をファイルに直接入れる方法(Ctrl-Vの次にEsc)も、ここで学びます。