* パート1 [#zf62d021] ** ファイルの中を見る [#wbba8b59] viエディタは、vi, view, exのコマンドを提供しています。 最初は、読込専用のviewを使ってファイルの中身を覗いてみましょう。 投稿が完了したので、このページの内容は削除しました。 /etc/protocolsファイルの内容を見てみましょう。 端末ソフトから以下のコマンドを入力して下さい。 ((最初の$ は、プロンプトで入力しません。)) #pre{{ $ view /etc/protocols }} 図1 &ref(th_Fig1.jpg); 画面の一番下には、ファイル名、"[readonly]"、行数、文字数が表示されます(図1参照)。 viewコマンドを使うことでファイルが読み込み専用として扱われていることが分かります。 *** 画面スクロール [#b24c3752] 矢印キーでカーソルを動かし、画面をスクロールさせることも可能ですが、 スクロールコマンドを使うと素速くスクロールさせることができます。 順方向のスクロールにはコントロールキーとfキーを同時に押す (以降Ctrl-F形式で表し、慣例でコントロールキーの後のキーは大文字で表記します) ことで、最後の2行が重なるようにスクロールします。 逆方向の複ロールは、Ctrl-Bです。 プログラムを追いかけるときには、1画面ではなく、ページの半分を動かしたくなりますが、 このような場合には、Ctrl-D(順方向半画面スクロール)とCtrl-U(逆方向半画面スクロール) を使います。 viでは、通常コマンドの前に数値を入力するとその回数分繰り返すとか行数を指定する意味に 解釈されます。 2Ctrl-Fは2画面分順方向にスクロールし、20Ctrl-Dとすると20行分順方向にスクロールします。 色々試してみて下さい。 表示画面が一部でファイルの終わりになった場合には、残りの行にはチルダ−(~)が表示されます(図2参照)。 図2 &ref(th_Fig2.jpg); また、行が長くてすべてを表示できない場合には、表示できない行を@で表示します(図3参照)。 ((/etc/protocolsには、長い行はないので、少し加工して表示しています)) 図3 &ref(th_Fig3.jpg); *** 指定した行を表示 [#n5470c6f] コンパイルエラー等で表示したい行数が分かっている場合には、行番号に続けてGを入力します。 行番号も一緒に表示するには、:set numberまたは省略して:set nuと改行を入力します(図4参照)。 ((:を入力すると画面の最下部にカーソルが移動し、ラインエディタモード(exモードと記す)になり、exコマンドの機能を使うことができます。)) 図4 &ref(th_Fig4.jpg); 行番号表示では、行番号の列と内容が重ならないように表示されます(図5参照)。 ((Mac OSXのviでは、行番号が色分けして表示されます)) 図5 &ref(th_Fig5.jpg); 行番号表示を解除して、元に戻すには、:set nonumberまたは省略してset nonuと入力します。 Gコマンドで行番号を省略すると最後の行にカーソルが移動します。また、exモードで :行番号と改行を入力することもできます。 *** タブを見る [#z80e5c2e] タブ区切りのデータファイルやMakefileでは、タブキーが重要な役割をしますが、 通常の画面表示では、タブの場所が確認できません。 :set listと改行を入力するとリスト表示に切り替わります。 タブキー等のコントロールコードは、^+コントロールコード形式で表示され、 タブの場合、^Iと表示されます。また、行の終わりには$が追加されます(図6参照)。 図6 &ref(th_Fig6.jpg); リスト表示から通常の表示に戻すには、:set nolistと改行を入力します。 *** 文字列の検索 [#tf78fe5a] ファイルの中身を見るときによく使うのが、文字列検索です。 viエディタでは、/の後に検索する文字列を入力して改行を押すことで、 文字列検索ができます。 また、ファイルの先頭に方向に向かって検索する場合には、?の後に検索する文字列を入力します。 早速、/etc/protocolsファイルで試してみましょう。 /protocolと改行を入力すると2行目のprotocolsの先頭にカーソルが移動します。 同じ検察文字列を続けてサーチするには、nを押します。検索したときと逆方向に サーチするには、Nを押します。 検索文字がファイルの終わりに達したら、またファイルの先頭から検索します。 その時、以下のメッセージを表示します。 #pre{{ search hit BOTTOM, continuing at TOP }} /etc/protocolsでprotocolという文字列は多く現れていますので、検索の練習によいでしょう。 *** エディタの終了 [#na4e44cf] これまで、viewを使ってファイルの中身を見てきましたが、エディタを終了には:qと改行を入力します。 viでは、ファイルの内容を変更した後に、保存しないで終了しようとすると図7の様な警告が表示されます。 #pre{{ E37: No write since last chage (add ! to override) }} ファイルへの変更を保存しないで、強制的に終了する場合には、:q!と改行のようにコマンドの後に!を付けます。 図7 &ref(th_Fig7.jpg); *** 複数のファイルを扱う [#a46ae85c] viewを含めviエディタでは複数のファイルを扱うことができます。 例として、/etc/apache2でhttpd関連の設定ファイルの中身を見てみましょう。 端末ソフトで以下の様に入力してください。MacOSXの場合、最初に/etc/apache2/httpd.conf が表示されました。 #pre{{ $ view /etc/apache2/httpd*.conf }} どんなファイルを表示しようとしたかは、:argsと改行を入力して知ることができます。 []で括られたファイルが現在表示しているファイルです。改行を押すと元の画面に戻ります。 図8 &ref(th_Fig8.jpg); 次のファイルに切り替えるには、:nと改行を入力し、一つ前のファイルに切り替える場合には:Nと改行を入力します。 他のviコマンドと同様にnやNの前に数値を入力するとn個後のファイルやn個前のファイルに切り替えることができます。 試しに、上記の状態で:3nと改行を入力してみます。 ファイルが3つ後のhttpd_corecollaboration_webauth.confに切り替わりました。 :argsと改行を入力すると、httpd_corecollaboration_webauth.confが[]で囲まれています。 #pre{{ httpd.conf httpd_ACSServer.conf httpd_corecollaboration_required.conf [httpd_cor ecollaboration_webauth.conf] httpd_corecollaboration_webcal.conf httpd_deviceman agement.conf httpd_mailman.conf httpd_passwordreset_required.conf httpd_podcastl ibrary.conf httpd_webdavsharing.conf httpd_webdavsharing_sharepoints.conf httpd_ webdavsharing_template.conf httpd_webmailserver.conf Press ENTER or type command to continue }} また、最初のファイルから見直す場合には、:rewまたは:rewindと改行を入力します。 複数ファイルを表示している途中(最後のファイルを表示する前)で終了しようとすると、 以下のエラメッセージを表示します。 この場合、:q!と改行で終了できます。 #pre{{ E173: xx more fiels to edit }} *** ファイルの中身を見るのに使ったコマンド一覧 [#b68c4715] これまで、使ってきたviewのコマンドを表1にまとめて示します。 | コマンドの機能 | 呼び出し形式 | 使用例 |h | viewの起動 | view ファイル名... | view /etc/protocols : /etc/protocolsを読込専用で表示 | | 順方向1画面スクロール | [n]Ctrl-F | Ctrl-F : 1画面順方向にスクロール、 3Ctrl-F : 3画面分順方向にスクロール | | 逆方向1画面スクロール | [n]Ctrl-B | Ctrl-B : 1画面逆方向にスクロール、 2Ctrl-B : 2画面分方向にスクロール | | 順方向半画面スクロール | [n]Ctrl-D | Ctrl-D : 半画面順方向にスクロール、20Ctrl-D : 20行順方向にスクロール | | 逆方向半画面スクロール | [n]Ctrl-U | Ctrl-U : 半画面逆方向にスクロール、40Ctrl-D : 40行逆方向にスクロール | | 指定行を表示 | [n]Gまたは:n改行 | nG : n行目が画面の中央に来るように表示、G : 最後の行を表示する | | 行番号を表示 | :set nu改行または:set number改行 | :set nu改行 : 画面左端に行番号を付加して表示 | | リスト表示 | :set list改行 | :set list改行 : タブは、^Iで行の終わりは$で表示 | | 順方向文字列検索 | /検索文字列改行 | /protocol : ファイルのprotocolという文字列を順方向に検索 | | 逆方向文字列検索 | ?検索文字列改行 | ?http : ファイルのhttpという文字列を現在位置から逆方向に検索 | | 前の検索文字列と同じ方向に検索 | n | /protocol改行の後にnを入力すると次のprotocolにカーソルを移動 | | 前の検索文字列と逆方向に検索 | N | /protocol改行の後にNを入力すると前のprotocolにカーソルを移動 | | 引数で与えたファイル一覧を表示 | :args改行 | :args : 現在表示中のファイルを[]で囲んで引数の一覧を表示 | | 次のファイルに切替 | :[n]n改行 | :n改行 : 次のファイルを表示、:2n改行 : 2つ後のファイルを表示 | | 前のファイルに切替 | :[n]N改行 | :N改行 : 一つ前のファイルを表示 | | 引数の先頭に切替 | :rew改行または:rewind改行 | :rew改行 : 先頭のファイルを表示 | | コマンドの終了 | :q [!] | :q改行 : コマンドの終了、:q!改行 : 強制終了 | *** コラム(3つの顔をもつエディタ) [#d9b76f7b] vi, view, exは同じプログラムで、呼び名によって振る舞いを変えています。 - viで起動された場合には、通常のviエディタとして機能 - viewで起動された場合には、読込専用のビューアとして機能 - exで起動された場合には、ラインエディタとして機能 このように、unixのコマンドにはargv[0]の文字列で処理を変える物が存在します。 更にMac OSXのvi, view, exを調べるとvimコマンドへのリンクになっていました。 ((時代の流れを感じますね。)) #pre{{ $ ls -l /usr/bin/{vi,ex,view} lrwxr-xr-x 1 root wheel 3 4 10 2012 /usr/bin/ex -> vim lrwxr-xr-x 1 root wheel 3 4 10 2012 /usr/bin/vi -> vim lrwxr-xr-x 1 root wheel 3 4 10 2012 /usr/bin/view -> vim }} * パート2 [#m5350ee8] ** viコマンドを使ってみる [#z934edab] viewコマンドでファイルの中身をみることができるようになったので、viコマンドでファイルの編集をしてみましょう。 *** カーソル移動 [#gce8b67d] カーソルの移動は、カーソルキー(←、↓、↑、→)も使えますが、viに割り当てられたキー(h、j、k、l)を使うと キーボードのホームポジションで楽にカーソルを移動することができます。 ((vi操作の基本は、ホームポジションを維持しながら、編集することです。そうすることで編集時の目の疲れが軽減され、間違いも少なくなります。)) これから説明するviのカーソル移動キーを図9に示します。 図9 &ref(Fig9.png); カーソルキーもキーの前に数値を入力すると、数値分繰り返したように移動します。 3jと入力すると3行下に移動します。 *** カーソル移動の練習 [#u1da5e3f] 以下の様なRougeの迷路の図があります(ローグ Wikipediaから引用)。画面から目を離さずに、h, j, k, lだけを使って上部の囲みの%から廊下#に沿って下部の囲みの^まで机上でカーソルを動かしてみて下さい。((素速く動かさないとモンスターHに襲われますよ)) &ref(rouge.png); *** 単語単位の移動 [#be7f9ca7] viでの単語は、C言語で扱い安いようにアルファベットと数字、アンダーライン(_)が続いて部分をword(以下小ワード単位と記す)として移動します。 図10を使ってカーソル移動を説明します。変数g_var0のgの位置にカーソルがあり、wを続けて入力することで、 カーソルが=, 1, ;に移動します(図11-a, 11-b, 11-c参照)。 今度は、;の位置でbを入力すると1, =, gと小ワード単位逆方向に移動します。 これに対して、スペース、タブ、改行などの空白類で区切られた単位をWord(以下大ワード単位と記す)と して移動するコマンドがWとBです。図10のg_var0のgの位置でWを続けて入力することで、 カーソルがifの先頭のi、(、!と空白類単位で移動します(図12-a, 12-b, 12-c参照)。 逆にBを入力すると(、i、gと最初の位置に戻ります。 また、小ワードの終わりに移動するにはe、大ワードの終わりに移動するにはEを使います。g_var0でeと入力 すると、0の位置にカーソルが移動し、gの位置からEを入力すると;に移動します(図13-a, 13-b参照) 図10 &ref(th_Fig10.jpg); 図11(a, b, c) &ref(Fig11-a.png); &ref(Fig11-b.png); &ref(Fig11-c.png); 図12(a, b, c) &ref(Fig12-a.png); &ref(Fig12-b.png); &ref(Fig12-c.png); 図13(a, b) &ref(Fig13-a.png); &ref(Fig13-b.png); *** 行内文字サーチ [#qdfa5819] カーソル位置から行末方向に文字を検索するコマンドがfで、f=のようにfの後に検索したい文字を入力します。 g_var0のgの位置でf=と入力すると=にカーソルが移動します(図14-a, 14-b参照)。 図14(a, b) &ref(Fig14-a.png); &ref(Fig14-b.png); 文字列サーチと同様に文字検索も前に検索した文字を記憶しており、同じ文字を検索するには、;を入力します。 次の行のifのiにカーソルを移動して、;と入力すると!=の=にカーソルが移動します。 もう一度;を入力してみてください。警告音が鳴ってカーソルは移動しません。 行内文字サーチなのでカーソル位置の後に検索文字がそれ以上見つからないと警告音で知らせます。 逆方向に文字検索するには、,を使います。 g_var0の行末;にカーソルを移動して、,と入力するとg_var0の後の=にカーソルが移動します。 fとは逆に行頭方向に文字を検索するには、Fを使います。 時には、検索文字の前にカーソルを移動したい場合があります。((後で説明する置換や削除コマンドと一緒に使います)) それにはtとTをfとFの代わりに使用します。g_var0のgの位置からt=と入力すると=の直前の0にカーソルが移動します(図15-a, 15-b参照)。 図15(a, b) &ref(Fig15-a.png); &ref(Fig15-b.png); 行内文字検索機能はディスプレイを見ながら目的の場所に素速くカーソルを移動する時にとても便利です。 *** 画面の先頭・中央・末尾への移動 [#r76da29b] タブや空白以外の行の先頭文字に移動する場合は^を使い、物理的な行の先頭に移動する場合には0(数字の0)を使います。 この逆に行の終わりに移動するには$を使います(図16-a, 16-b, 16-c参照)。 図16(a, b, c) &ref(Fig16-a.png); &ref(Fig16-b.png); &ref(Fig16-c.png); 画面の中央の行頭に移動するにはMと使い、画面上部先頭に移動するにはH、下部先頭に移動するはLを使います。 もちろん2Hと入力すると画面上から2行目行頭に移動し、2Lとすれば画面下部から上に2行目の行頭に移動します。 *** ちょっと便利なカーソル移動 [#c18dcbe3] これまでのカーソル移動キーを使えば、画面を見ながら自分の思ったところにカーソルが移動できるように なります。 ここからカーソル移動の小技として、以下の2つを紹介します。 - カッコの対に移動 - マーク機能 最初にカッコの対に移動するには、%を入力します。 (), [], {}などの括弧にカーソルを移動し、%を入力すると対応する括弧の位置にカーソルが移動します。 ((カーソル位置に括弧存在しない場合、カーソルが属している範囲の先頭の括弧に移動します)) この機能は、Cやjava言語などのプログラミンで役に立ちます。 例として、図10のmain()の後の{にカーソルを移動し、%を入力するとファイルの終わりの}にカーソルが移動します。 更に、一つ上の}に移動して%を入力するとif文の最後の{にカーソルが移動します(図17-a, 17-b参照)。是非自分で試して見てください 図17(a, b) &ref(Fig17-a.png); &ref(Fig17-b.png); 次の小技は、マーク機能です。前に編集していた場所に移動するには、''と'(シングルクォート)を続けて2回入力します。 g_var0のgの位置から文字検索機能(/})で画面下から2番目の}に移動した後に''を入力すると、元のg_var0のgの位置に カーソルが戻ります。 'はマーク参照コマンドでマークコマンドmでマークされた場所にカーソルを移動するのに使います。 試しに3行目のint g_var0のiにカーソルを移動し、maと入力します。これでiの場所がaというマーク名で記憶されます。 ((マーク名には、aからzのアルファベットを使用します)) 一度記憶された場所は、どこからでも参照できます。Lで行の最後に移動して'aと入力してみてください。 ここで'aと入力すると、カーソルは3行目先頭のiの位置に移動します。 ((マーク機能はexモードで、編集範囲を指定する場合にも利用できます)) *** カーソル移動コマンド一覧 [#a0fc6150] カーソル移動コマンドを表2にまとめました。図9と一緒に見ながら、コマンドの使い方を確認してみてください。 | コマンドの機能 | 呼び出し形式 | 使用例 |h | 左へ移動 | [n]h | h : 1文字左へ移動、3h : 3文字左へ移動 | | 右へ移動 | [n]l | l : 1文字右へ移動、2l : 2文字右へ移動 | | 上へ移動 | [n]k | k : 1行上へ移動、3l : 3行上へ移動 | | 下へ移動 | [n]j | j : 1行下へ移動、2j : 2行下へ移動 | | 次の小ワードへ移動 | [n]w | w : 次の小ワードへ移動、3w : 3つ次の小ワードへ移動 | | 前の小ワードへ移動 | [n]b | b : 前の小ワードへ移動、2b : 2つ前の小ワードへ移動 | | 次の大ワードへ移動 | [n]W | W : 次の大ワードへ移動、3W : 3つ次の大ワードへ移動 | | 前の大ワードへ移動 | [n]B | B : 前の大ワードへ移動、2B : 2つ前の大ワードへ移動 | | 小ワードの終わりへ移動 | [n]e | e : 小ワードの終わりへ移動、3e : 3つ目の小ワードの終わりへ移動 | | 大ワードの終わりへ移動 | [n]E | E : 大ワードの終わりへ移動、2E : 2つ目の大ワードの終わりへ移動 | | 順方向行内文字検索 | [n]fc | f= : 行内の次の=に移動、3f, : 行内の3つ目の,に移動 | | 逆方向行内文字検索 | [n]Fc | Fg : 行内の前のgに移動、2F0 : 行内の2つ前の0に移動 | | 前の文字検索を繰り返す | ; | ; : 前回のfやFの行内文字検索を繰り返す | | 前の文字検索と逆方向に行内検索 | , | , : 前回のfやFとは逆の方向に行内文字検索をする | | 行の非空白先頭へ移動 | ^ | ^ : タブや空白以外の行の先頭へ移動 | | 行の物理的先頭へ移動 | 0 | 0 : 行の物理的な先頭へ移動 | | 行の終わりへ移動 | $ | $ : 行の終わりへ移動 | | 画面の中央の行頭へ移動 | M | M : 画面の中央の行頭へ移動 | | 画面上部行頭へ移動 | [n]H | H : 画面上部行頭へ移動、2H : 画面上から2行目行頭へ移動 | | 画面下部行頭へ移動 | [n]L | L : 画面下部行頭へ移動、3L : 画面下部から上に3行目の行頭へ移動 | | 対の括弧へ移動 | % | % : カレント位置にある括弧の対の括弧へ移動 | | カレント位置マーク | mc | ma : カレント位置をマークaとして登録 | | マーク位置へ移動 | 'c | 'a : マークaへ移動、'' : 前のカーソル位置へ移動 | ** 編集コマンド [#a2a08d6c] これまで説明したカーソル移動が自由にできるようになったら、viエディタの7割はマスターしたと 言ってよいでしょう。後は簡単な編集コマンドを覚えるだけです。 *** 編集コマンドの一般形式 [#kf5f524f] viエディタの編集コマンドには、以下の2つのパターンがあります。 - [n]コマンド・[m]カーソル移動(カーソル移動で指定された範囲の編集) - [n]コマンド・コマンド(行単位の編集) 最初の例として、2小ワード削除(dコマンド)の例を示します。 図18-aのg_var0の位置にカーソルがあり、ここで2dwまたはd2wと入力するとg_var0=までの文字列が削除されます(図18-b)。 図18(a, b) &ref(Fig18-a.png); &ref(Fig18-b.png); 2つめの例として、カレント位置以降の3行を削除する例を示します。 図19-aのif文の先頭にカーソルがあり、3ddと入力するとif文から3行が削除されます(図19-b)。 図19(a, b) &ref(Fig19-a.png); &ref(Fig19-b.png); *** viのモードについて [#ib470496] viを分かりづらくしているものにエディタのモードがあります。 viには、以下の4つのモードがあり、ユーザはこれらのモードを使い分けています。 - カーソル移動モード - インサートモード - オーバーライドモード - exモード 最初のカーソル移動モードは、これまで練習してきたカーソル移動や文字列検索で 画面を移動する時のモードです。 次にインサートモードは、挿入、追加、行追加コマンドなどに文字列をインサートしていることを示すモードです。 オーバーライドモードは、上書き置換コマンドで既存の文字列を上書きしながら編集していることを表す示すモードです。 最後のexモードは、:(コロン) の後にexコマンドを入力している時のモードです。 *** 挿入 [#q289192a] 文字列の挿入(insert)には、カーソル位置の直前に挿入するiコマンドとカレント行の空白以外の先頭に挿入するIコマンドがあります。 図10のgvar0の後の=にカーソルを移動してiコマンドを入力すると、図20-aのように画面の最下行に-- INSERT--と表示されます。 これで現在のモードが、インサートモードであることをユーザに知らせています。ここで、insertと文字列を入力し、最後にエスケープキー(以下Escと記す)を押すと挿入が完了します(図20-b参照)。 図20(a, b) &ref(th_Fig20-a.jpg); &ref(Fig20-b.png); 挿入を取り消す(undo)場合には、uコマンドを入力します。 また、文字列を入力し直したいときには、バックスペースで戻るよりCtrl-Uを使った方が簡単です。 行の先頭に*を5個追加したいときには、5I*Escと入力すると図21のように*****が行の先頭に追加されます。 図21 &ref(Fig21.png); *** 追加 [#u29b800c] 文字列を追加(append)には、カーソル位置の後に追加するaコマンドとカレント行の末尾に追加するAコマンドがあります。 図10のgvar0の後の=にカーソルを移動してaコマンドを入力して、appendに続いてEscを押すと=の後にappendが追加されます。 &ref(Fig22.png); データ入力などではカラム番号を確認したいときがあります。 このようなときには、空の行(以下空行と記す)で8a....+....*に続いてEscを押すと図23の様に表示されます。 図23 &ref(th_Fig23.jpg); *** 削除 [#rccf922f] 削除(delete)コマンドには、dコマンドとカーソル位置から行末まで削除するDコマンドがあります。 Dコマンドや次のCコマンドは基本的にd$とc$のエリアス(別名)に過ぎないので覚える必要はありません。 図10のg_var0のgにカーソルを移動して、dwと入力すると小ワード単位のg_var0が削除されます(図24参照)。 図24 &ref(Fig24.png); uコマンドで元に戻して、行単位の削除をします。ddと入力するとカレント行が削除されます(図25-a参照)。 前のコマンドを繰り返すには、.(ピリオド)を使用します。...とピリオドを3回入力してみてください、 行単位の削除が繰り返され図25-bのようになります。 図25(a, b, c) &ref(Fig25-a.png); &ref(Fig25-b.png); 削除された文字列は1〜9までの数字バッファに記憶されています。 "1Pと入力すると最後に削除した文字列が復活します(図25-c参照)。更に...とピリオドを3回入力してみてください。 元の図10の状態に戻ります。 &ref(Fig25-c.png); *** 置換 [#q8d94641] 使用頻度の高い置換(change)には、cコマンドを使います。 図10のgにカーソルがある状態でcwCangeに続いてEscを押すと、図26のようになります。 図26 &ref(Fig26.png); 行単位の修正の場合には、ccコマンドを使います。 今回は、図10の=の場所にカーソルを移動し、ccCHANGEに続いてEscを押して見て下さい。 ccで行の初めにから終わりまでの文字列が消えて、インサートモードに入ります(図27-a参照)。 この後変更する文字列CHANGEに続いてEscを押すと図27-bのようになります。 図27(a, b) &ref(th_Fig27-a.jpg); &ref(Fig27-b.png); *** 上書き置換 [#me446364] Rコマンドによる上書き置換は、終わりの部分の修正漏れがでることが多いので((単に私がミスが多いだけです)) あまり使うことはありませんが、一応紹介しておきます。((vi使いならRは使いません)) 図10のgにカーソルがある状態でRreplaceに続いてEscを押すと、図28のようになります。 意味のない単位で修正が行われるため、上書き置換を使う時には、注意が必要です。 図28 &ref(Fig28.png); *** 行追加 [#va79a1ec] 行の追加(open)には、カーソル行の下に行を挿入するoコマンドとカーソル行の上に挿入するOコマンドがあります。 どちらも動作は同じなので、ここではoコマンドの使い方を例に説明します。 図10のgにカーソルがある状態でoと入力すると、図29-aのようにカーソル行の下に1行追加され、インサートモードに入ります。 ここで、Open lineに続いてEscを押すと図29-bの様になります。 この例では、autoindent設定が有効になっているので、g_var0と同じ位置まで自動的にインデントされています。 Cやjava言語の場合にはautoindentではなく、cindentを使った方が便利です。設定方法については、後の環境設定を参照してください。 図29(a, b) &ref(th_Fig29-a.jpg); &ref(Fig29-b.png); *** 一文字置換 [#t2c960d1] C言語の配列の添え字を変える場合に1文字単位の置換をしたいときがあります。 このような時には、clコマンドよりも一文字置換のrコマンドを使う方が便利です。 図10のg_var0のgをlに置換する場合には、rlを入力するだけで、Escを押す必要もありません。 図30 &ref(Fig30.png); *** コピー&ペースト [#jc929547] コピー&ペーストのコピー(yank)には、yコマンドを使います。ペースト(paste)には、カーソル位置の後にペーストするp コマンドとカーソル位置の前にペーストするPコマンドを使います。 図10の変数g_var0をコピーして、mainの上の行にペーストしてみましょう。 g_var0のgにカーソルを移動し、ywとした後にmain()の上の空行に移動して、pと押すと図31のようにg_varを コピー&ペーストできます。 図31 &ref(Fig31.png); 削除コマンドと同様にコピーコマンドの文字列を名前付きバッファに保存することができます。 図10のprintf文の1行を名前付きバッファaに記憶して、main関数の後に追加してみます。 以下の一連の文字列を入力して、動きを確認してみてください(図32参照)。 #pre{{ /printf "ayyG"ap }} 名前付きバッファを使うメリットは、ペーストの後に編集をして一時バッファの内容が変わっても、 名前付きバッファからペーストすることで、コピーしたときと同じ文字列をペーストできることにあります。 図32 &ref(Fig32.png); *** ファイルの書き込み [#w5fcb31c] 編集した結果をファイルに上書き保存するには、:wと改行を入力します。 そのまま終了するには、:wqと改行を入力します(図33参照)。((ZZでも同じ処理ができますが、ZZは間違ってCtrl-Zを押す危険があるので、:wq改行を使うようにしてください。)) 図33 &ref(th_Fig33.jpg); 別名で保存する場合には、:w ファイル名に続いて改行を入力します。 この場合、カレントファイルが別名のファイルになりますので、元のファイルに戻るには:e#と改行を押します。 :eコマンドは、別のファイルを編集するときにも使えます。現在の変更を破棄して切り替えるには、:e! ファイル名のようにeの後に!を付けます。 一度に複数のファイルを編集して、すべて保存して切り替える場合には、:set autowriteを設定すれば切替時に自動的に保存します。 *** viエディタの環境設定 [#p0fe4de4] viエディタの設定をホームディレクトリ直下の.exrcに書き込んでおくことで、毎回設定することを省略できます。 例えば、C風のインデントとタブを空白4個に置換するように設定するには、.exrcを以下の様に定義します。 #pre{{ set cindent set sw=4 set ts=4 }} cindentをセットすると、while {改行と入力すると自動的にインデント(字下げ)してくれます(図34参照)。 図34 &ref(th_Fig34.jpg); *** 外部コマンドの利用 [#l4ba8ff6] viエディタの中からlsやsort等の外部コマンドを実行してその結果を表示することができます。 例として、カレントディレクトリのファイル一覧を表示してみます。 :! lsと改行を入力するとlsの結果が表示され、Press ENTER or type command to continueのメッセージがでますので、 改行を入力すると元の画面に戻ります。 図35 &ref(th_Fig35.jpg); lsの結果をファイルに取り込みたいことがあります。その場合には、lsの結果と置き替えたい行に移動し、 !! lsと改行を入力します。 図36 &ref(th_Fig36.jpg); ファイル全体をコマンドに渡して、その結果と置き替えるには、:%! コマンドの形式で行います。 例として、ファイル内容をソートした結果と置き替えてみましょう。 :%! sortと改行を入力すると図37のようにソートされた結果と置換されます。 図37 &ref(th_Fig37.jpg); *** 知っていると便利なコマンド [#d882defc] 知っていると便利なコマンドに大文字と小文字のトグルコマンド~とシフトコマンドがあります。 図10のg_var0のgから~を続けて押して;に移動してみてください(図38参照)。~は、アルファベットに対してのみ作用するので、数字や記号はそのままです。 図38 &ref(Fig38.png); インデントを変えるには、シフトコマンド<<と>>を使用します。見たとおり<<は左にシフトし、>>は右にシフトします。 図10のg_var0の位置で4<<と実行すると図39の様に4行が左にシフトします。 図39 &ref(Fig39.png); *** 編集コマンド一覧 [#ib4e97fe] 編集コマンドはその意味から容易に想像できるので、覚えるのも簡単だと思います。 表3に編集コマンドの一覧をまとめました。編集コマンドの使い方に不安になったときに参照して下さい。 | コマンドの機能 | 呼び出し形式 | 使用例 |h | カーソル位置の直前に挿入 | [n]iテキストEsc | iHelloとEsc : カーソル位置の前にHelloを挿入 | | 行の先頭文字の直前に挿入 | [n]IテキストEsc | 5I*とEsc : 行の先頭文字の前に*****と*を5個挿入 | | カーソル位置の直後に追加 | [n]aテキストEsc | aWorldとEsc : カーソル位置の直後にWorldを追加 | | 行の終わりに追加 | [n]AテキストEsc | Aafter end of lineとEsc : 行の終わりにafter end of lineを追加 | | カーソル位置からの削除 | [n]dカーソル範囲Esc | 2dw: カーソル位置から2小ワード分を削除 | | カーソル行からn行削除 | [n]dd | 3dd : カーソル位置らから3行削除 | | カーソル位置からの置換 | [n]cカーソル範囲テキストとEsc | cwChangeEsc : カーソル位置から小ワード分をChangeに置換 | | カーソル行からn行置換 | [n]ccテキストEsc | 3ccChange of linesとEsc : カーソル行から3行をChange of linesに置換 | | カーソル行からの上書き置換 | [n]RテキストEsc | RreplaceとEsc : カーソル行から7文字分をreplaceに置換 | | カーソル行の下に行を挿入 | [n]oテキストEsc | oOpen lineとEsc : カーソル行の下にOpen lineと行を挿入 | | カーソル行の上に行を挿入 | [n]OテキストEsc | 2OとEsc : カール行の上に2行の空行を挿入 | | カーソル行1文字を置換 | r文字 | rl : カーソル位置の文字をlに置換 | | カーソル位置からのコピー | ["名前]yカーソル範囲 | yw : カーソル位置から小ワード分をコピー | | カーソル行からのコピー | ["名前][n]yy | "a2yy : カーソル行から2行を名前aのバッファにコピー | | カーソル位置の後にペースト | ["名前]p | p : バッファの内容をカーソル位置の後にペースト | | カーソル位置の前にペースト | ["名前]P | "aP : 名前aのバッファの内容をカーソル位置の前にペースト | | 外部コマンド連携 | [n]!!外部コマンド改行 | !!wc -wと改行 : カーソル行の内容をwcに渡し、語の数に置き替える | | 大文字小文字の入替 | ~ | ~ : カーソル位置のアルファベットの大文字と小文字を入れ替える | | コマンドの取消 | u | u : 直前のの処理を取り消す | | コマンドの繰り返し | . | . : 直前の処理を繰り返す | | ファイルへの上書き保存 | :w[!]改行 | :wと改行 : 現在の内容をファイルに上書き保存 | | 別名で保存 | :w ファイル名改行 | :w otherと改行 : 現在の編集内容をotherファイルに保存 | | ファイルの切替 | :e ファイル名改行 | :e beforeと改行 : beforeファイルに編集対象を切り替える | * パート3 [#m3ae8a90] ** exコマンド [#z81f6486] exコマンドとは、viのラインエディタを差します。 今では死語に近いラインエディタ((行単位での編集エディタ))の機能ですが、便利なコマンドが用意されています ここではexコマンドの雰囲気を味わって貰う程度で紹介します。 *** exコマンドの形式 [#s6f7d8f5] viエディタでは、:の後に続くのがexコマンドです。 exコマンドの入力形式は、以下の様になっています。 #pre{{ :[アドレス範囲]コマンド[コマンド引数]と改行 }} - アドレス範囲では、コマンドを適応する行nまたは範囲を行番号n,m形式、/from RE/,/end RE/の正規表現、アドレス'n,'mで指定することができます - コマンドには、プリント(print)のpコマンド、置換(substitute)のsコマンドなどがあります - コマンド引数には、コマンドに渡される引数を与えます アドレス範囲の例としては、以下の様な指定がよく使われます。 - 3 : 3行目を編集対象とすることを意味します - 1,$ : これは、1行目から最後の行までという意味で、%を使うこともあります - 'a,'b : マークコマンドで指定したマークaからマークbまでという意味 - /start/,/end/ : カーソル行以降のテキストにstartを含む行から、テキストにendを含む行までという意味です *** 正規表現 [#e507c45e] 正規表現(Regular Expressionを略してREと記す)は、検索したい文字列のパターンを形式的な表現で表したものです。 例えばaとbの間に任意の1文字が入っている文字列を検索する場合には、a.bとピリオド(.)を使って任意の一文字を表します。 表4に正規表現で使われる記号とその意味について簡単に示します。無理に全部覚えようとしないで、少しずつ試してみてください。 表4 | 正規表現 | 意味 | 使用例 |h | . | 任意の1文字 | a.b : aとbの間に任意の1文字にマッチ | | ^ | 行の先頭 | ^abc : 行の先頭がabcで始まる場合にマッチ | | $ | 行の終わり | abc$ : 行がabcで終わる場合にマッチ | | [abc] | 文字の列挙 | [efg] : カギ括弧で指定されたefgのいずれか1文字にマッチ | | [a-z] | 文字の範囲 | [A-Z] : AからZまでのいずれか1文字にマッチ | | [^abc] | 指定以外の1文字 | [^a-z] : aからz以外の1文字にマッチ | | * | 直前のパターンの0回以上の繰り返し | [0-9][0-9]* : 数字の繰り返しにマッチ | 正規表現を使うと複雑なパターンも簡単に検索することができます。 例えば、abで始まって数字で終わる文字列を見つけるには、ab.*[0-9]と指定します。 これはabの後に任意の文字が0回以上繰り返され、0から9の数字で終わる文字列と読み替えると分かりますか。 *** grepの由来 [#x624f3e4] unixのコマンドにgrepという文字列検索のコマンドがあります。 どうしてgrepというコマンドが文字列検索なのか不思議に思った人も多いことでしょう。 grepは、exコマンドの:g/RE/pと同じ機能で、グローバル(Global)に正規表現(RE)を検索してプリント(Print)を つづめてgrepとしてしたものです。 図40-aのような1から6の数字だけのテキストで、2と4を含む行を表示するには、:g/[24]/p改行と入力すると、 図40-bのように2と4を含む行が画面下部に表示されます。 Press ENTER or type command to continueとでますので、改行を押すと元の画面になります。 図40(a, b) &ref(th_Fig40-a.jpg); &ref(th_Fig40-b.jpg); *** 一括置換 [#ob7a47b0] 文字列の一括置換に、exコマンドは欠かせません。 一括置換(Substitute)には、sコマンドを使用します。sコマンドの使い方は以下の通りです。 通常置換は、行の検索文字列にマッチした最初の文字列にのみ実施されますが、gオプションを追加すると行内の一致するすべての文字列に対して置換が行われます。 #pre{{ :[アドレス範囲]s/検索文字列の正規表現/置換文字列/[g]と改行 }} 図40-aのデータに対し、以下のコマンドを入力して2と4をAに置き替えてみましょう。2行目と4行目がAに置きかわっています(図41参照)。 #pre{{ :%s/[24]/A/と改行 }} 図41 &ref(th_Fig41.jpg); 検索文字列を置換文字列に含めるには&を使います。 例えばディレクトリ内のファイルのバックをアップ作成するときには、viエディタで以下の様な操作をします。 先頭に#の付いた行はコメントです。 このようにviエディタでコピーするファイルを選択したり、スクリプトを確認してからshに流し込むことで、 必要なファイルのみをバックアップできます。 #pre{{ # viを起動する $ vi # lsコマンドの結果をエディタに取り込む(図42-a) !!ls # ファイル一覧から、cp ファイル ファイル.bakに置換する(図42-b) :%s/.*/cp & &.bak/ # スクリプトをshで実行する(図42-c) :%! sh # 結果を見る(図42-d) !!ls }} 図42(a, b, c, d) &ref(th_Fig42-a.jpg); &ref(th_Fig42-b.jpg); &ref(th_Fig42-c.jpg); &ref(th_Fig42-d.jpg); *** その他の便利な使い方 [#we88bd79] ちょっとしたTipsですが、知っていると便利な使い方を紹介して終わりにします。 - grepとの連携 例えばmainを含むファイルのみを編集したい場合、以下の様にviを起動します。 #pre{{ $ vi `grep -l main *.c` }} - 起動時に指定行にジャンプ(vi +行番号 ファイル名) 次にviでファイルを開いたときに指定した行やパターンにジャンプして欲しい場合、+行番号または+/パターンを使います(図43参照)。 #pre{{ $ vi +/main 1.c }} &ref(th_Fig43.jpg); - tagsファイルの活用 viは、tagsファイルと呼ばれるファイルを使ってそのタグが現れるファイルの箇所にすばやく切り替える機能を持っています。 Cのプログラムに対してtagsファイルを作成するコマンドがctagsです。以下のコマンドで1.c, 2.cのtagsファイルを作成してみます。tagsファイルの中身は、タグ名、ファイル名、タグを検索する正規表現をタブで区切ったものです。 #pre{{ $ ctags *.c $ cat tags M11.c/^main() {$/ add22.c/^int add2(int a, int b) {$/ }} ここで、1.cのadd2でCtrl-]を入力すると(図44-a参照)、add2の定義にジャンプします(図44-b参照)。 ジャンプ元に戻るには、Ctrl-^を入力すると、mainのadd2の呼び出し元に戻ります(図44-c参照)。 このようにtagsファイルを使うと簡単に定義先と呼び出し元の切替が行えます。 図44(a, b, c) &ref(th_Fig44-a.jpg); &ref(th_Fig44-b.jpg); &ref(th_Fig44-c.jpg); 今回のviエディタの説明が皆様のお仕事で少しでもお役に立てると幸いです。 *** コラム(vi使いの音) [#hbbe1496] viのエキスパート((このような人を私はvi使いと呼んでいます))のviを使っているときのキーボードの音には、 ある種の特徴があります。 #pre{{ タン、タカタカタン タタン、タカタカタカタカ、パン タタン、タタン、タタン タン、タタタン }} これは、次のような操作をしているときの音です。 #pre{{ /g_var改行 cwlocal_vEsc n.n.n. :wq改行 }} プログラムの中からg_varという変数を検索し、local_vに置換し、検索と置換を3回繰り返し、 ファイルを保存して終了する一連の操作です。理由は分かりませんが、vi使いはEscを強く打ちます。 vi使いは同じことを繰り返すのを嫌い、如何にして簡潔にエディットを終了するかにこだわります。 あなたの廻りにはvi使いの人はいらっしゃいますか? ** 編集者のコメント [#a503d979] 内容についての感想をお聞かせ下さい。 スパム防止に画像の文字列も入力してください。 #comment_kcaptcha コメントを下さった方々に感謝申し上げます。