今回も古くから使われているエディタviのネタです。今回はもう少しviを活用してみましょう。viはUNIX上で開発されたので、コマンドラインからの入力を利用したりする事ができます。
各種処理において何でもコマンド一発で済めばらくですが、現実的には例外が多くあり、どうしても手作業で行わなければならない事があります。
そんな場合に活用できるのがviです。これができる限りはviがなくなることはないような気がします。
今回もこれまでのようにサンプルで利用するファイル・ディレクトリはデスクトップのsampleディレクトリとしています。デスクトップにsampleディレクトリがない場合は作成しておいてください。(コマンド入力ならmkdir ~/Desktop/sampleとして作成することができます)
なお、前回と同様の注意事項ですがキーボードのcaps lockはオンになっていないものとします。これはviでは大文字と小文字でのキー入力結果が異なるというのが1つと、macOSではshiftキーと英文字キーを押した場合の動作がUNIX/Windowsと異なるためです。
ビジュアルモード
viには視覚的に分かりやすく示すビジュアルモードがあります。ビジュアルモードにするにはv,V,ctrolキーとv(Windowsではq)のいずれかをノーマルモードで押します。それぞれに以下のようになります。
v 文字単位での選択
V 行単位での選択
controlキーとv (Windowsではq) 矩形ブロック単位での選択
コピーする範囲に応じて上記のいずれかのキーを押します。ビジュアルモードでは範囲を選択してから各種キーを押す事で削除や追加できます。ビジュアルモードを使うと、どこが選択されているのかわかりやすくなります。
なお、上記のキーを押す前にはコピー開始位置までカーソルを移動させておいてください。ここらへんGUIだとマウス操作で適当に選択するということができて楽だなあと思ったりもします。
ビジュアルモードで特に視覚的にわかりやすくできるのが次に説明するコピー(ヤンク)処理です。
コピー(ヤンク)&ペースト(プット)
viではコピー(viではヤンク)はyキーを押します。コピーした内容をペースト(viではプット)するにはペーストしたい位置までカーソルを移動させてからpキーを押します。
まずは文字単位でコピー(ヤンク)してペーストしてみましょう。vキーを押してからコピー(ヤンク)したい文字をカーソルを移動させて選択します。選択したらyキーを押します。yキーを押すとビジュアルモードでの選択は解除されます。
次にペーストしたい位置までカーソルを移動させます。カーソルを移動させたらpキーを押します。
ここでviの便利(面白い)なところですが、コピーした内容を5回ペーストしたい場合、とても簡単にできます。ペーストしたい位置までカーソルを移動させ5pと入力するとコピー(ヤンク)した内容が5回ペーストされます。
1000回(?)ペーストしたい場合でもviなら1000pと入力するだけです。ここらへんviはスケーリングしやすいので便利なこともあります。1文字コピーして1000pとすれば1000文字ペーストできるわけです。でも、そんなに大量にペーストすることはないかもしれませんが、以前解説したPBM/PPMなどではコピー(ヤンク)と大量の繰り返しペーストが役立つことがあります。画像の場合、同じ文字列の繰り返しが結構多く発生するからです。テキストから画像データを生成する方法については以前の連載を参照してください。
・テキストから画像を作成する(1)
https://news.mynavi.jp/techplus/article/natonakucommand-13/
・テキストから画像を作成する(2)
https://news.mynavi.jp/techplus/article/natonakucommand-14/
手作業で選択する時に便利なvi
viは標準入力からのテキストを受け取って編集する事ができます。標準入力からのデータを受け取って処理するのはUNIX系では珍しくありません。viはコマンドモードと組み合わせる事で人間が介在して判断しなければならない場合に威力を発揮します。
例えば以下のようなテキストファイルがカレントディレクトリにあるとします。
1.txt
01.txt
2.txt
footer.txt
ここで01.txt以外のテキストファイルを削除したいとします。以下のようにコマンドを入力します。viの後に-を指定するのを忘れるとエラーになるので注意してください。
ls *.txt | vi -
するとviにファイルパスが流し込まれます。
ここで削除したくない01.txtの行までカーソルを移動させddとキーを押して行を削除します。最初の段階でカーソルは01.txtになっているのであれば特にカーソルを移動させる必要はありません。
次にノーマルモードからコマンドモードにします。念のためescキーを押してから:キーを押します。
コマンドモードで以下のように外部コマンドを実行する!を使って削除します。ここでは削除コマンドのrmを使います。ここでxargsと組み合わせることで該当するファイルが削除されます。すると、編集されたパスのファイルだけが削除されます。
w !xargs rm
この例ではファイルの削除でしたが、書籍などで複数ある原稿をまとめる場合にも使えます。
まず、連結するファイルは以下のようになっているものとします。
intro.txt
chap1.txt
chap1.old.txt
chap2.txt
footer.txt
ここで、原稿を一旦連結したいところですが、バックアップ用に残してあるchap1.old.txtは連結されては困ります。catコマンドでさっくりと連結したいところですが、ファイルの命名規則もいまいちです。
そんな時に便利なのがviです。パイプを使って連結するファイルパスを流し込んでしまいます。先ほどのファイル削除と同様にオプションで-を付けておく必要があります。
ls | vi -
連結したくないファイル名は削除します。削除する行までカーソルを移動させてからddと入力すれば行が削除されます。もし、連結順を変えたい場合はこの段階で変更しておきます。
あとはescキーを押してから:キーを押してコマンドモードにします。以下のように入力するとカレントディレクトリにall.txtというファイルで各ファイルの内容が連結されます。
w !xargs cat > all.txt