vi と腕試し

INPUT · スライド

探して、置き換える

01 / 08

行番号が分からないとき

ここまでで vi はだいぶ使えるようになったね。でも、まだ困る場面があるんだ。

300行の設定ファイルの中の"port" と書いてある行を直したい

何行目かが分からないでしょう。3G は行番号を知っていないと使えないんだ。

j を押して目で探すこともできるけれど、300行は無理だよね。

だから中身で探すんだ。

/port → ⏎

port と書いてある行へ飛ぶでしょう。これがこの回の主役だよ。

grep に似ていると思ったかな。そのとおりだよ。

grep port settei.conf     どの行にあるか(章5)vi の中で /port           その行へ飛ぶ

探すという用事は同じで、grep は見せてくれ、vi は連れて行ってくれるんだ。

もう1つ、この回でやることがあるよ。

:%s/80/8080/g

まとめて置き換えるんだ。sedvi の中でやるようなものだね。

sed 's/80/8080/g' ファイル   出力を作る(章5)vi の :%s/80/8080/g          開いているファイルを直す

この回で持って帰るものはこれだよ。

/語 n     下へ探す・次へ?語       上へ探す:s        今の行を置き換える:%s       全部の行を置き換える

探せるようになれば、vi は完成だよ。あとは腕試しだけでしょう。

02 / 08

/ で探して飛ぶ

打ち方はこうだよ。

1. Esc(命令モードにする)2. / を打つ(画面の下に / が出る)3. 探す言葉を打つ4. ⏎

: と同じで、画面のいちばん下に打つ場所が出るでしょう。

/port

を押すと、カーソルがその言葉のところへ飛ぶんだ。

1つ、覚えておいてほしい性質があるよ。

> / は、いまの行より下から探す

1: port 80     ← いまここに居る2: host web13: port 80

この状態で /port を打つと、3行目へ飛ぶんだ。1行目は飛ばされるでしょう。

いまの場所より先を探す

これは親切なんだ。いまの場所で止まってしまったら、次を探せないからね。

見つからないとどうなるか、も知っておいてね。

/naimono → ⏎Pattern not found

「見つからなかった」と出るんだ。そしてカーソルは動かないよ。

見つかった   飛ぶ見つからない 動かない(メッセージが出る)

ここが大事だよ。動いたつもりで dd を押すと、いま居る行が消えてしまうでしょう。

/naimono → ⏎(動いていない)dd            ← いまの行が消える!

だから探したあとは、画面を見て「飛べたか」を確かめるんだ。画面のいちばん下の行番号が変わったかを見ればいいよ。

- settei.conf 1/5 20%  ↓ /log → ⏎- settei.conf 4/5 80%     ← 飛べた

数字が変われば飛べたでしょう。この確かめを挟むだけで、事故が防げるんだ。

03 / 08

n で次へ、? で上へ

同じ言葉が何回も出てくるファイルでは、n を使うよ。

n    次の一致へ
/port → ⏎    1つ目へn             2つ目へn             3つ目へ

探す言葉を打ち直さなくていいでしょう。n は next(次)だよ。

最後まで行くとどうなるかというと、こうだよ。

最後の一致で n を押す先頭に戻って、また探す

ぐるぐる回るんだ。だから n を押し続けると、同じ場所を何周もするよ。

上へ探すものもあるよ。

?語 → ⏎    上へ探す
/    下へ探す?    上へ探す

向きが違うだけだね。ファイルの後ろのほうに居て、前に戻りたいときに使うんだ。

使い分けの目安はこうだよ。

gg してから /語     ファイルの頭から順に見るG してから ?語      末尾から逆に見る

端に行ってから探すと、確実に1つ目から見られるでしょう。/ は「いまより下」だから、途中に居ると前のほうを見落とすんだ。

実際の使い方を書いておくね。

vi settei.confgg          頭に戻る/port → ⏎   1つ目の port へ(直す)n           次の port へ(直す)n           次の port へ

探して直して、次へという繰り返しでしょう。これが実務でいちばん多い vi の使い方かもしれないね。

前の回の . と組み合わせると、もっと速くなるよ。

/port → ⏎   飛ぶdd          消すn           次へ.           同じように消す

探して、繰り返すんだ。同じ直しを何か所にもやるときの型だよ。

04 / 08

:s で置き換える

探して飛んだら、直すでしょう。でも「同じ直しを20か所」なら、まとめてやりたいよね。

そのための命令だよ。

:s/古い/新しい/
port 80  ↓ :s/80/8080/port 8080

: から打つんだ。:wq:3 と同じ入口だね。

読み方はこうだよ。

:s      substitute(置き換える)/80/    探すもの/8080/  置き換えるもの

スラッシュで区切るでしょう。章5の sed とまったく同じ書き方だよ。

sed 's/80/8080/' ファイルvi の :s/80/8080/

s の部分が同じなんだ。だから章5をやった人には、もう見覚えがあるでしょう。

:s だけだと今の行だけが対象だよ。

:s/80/8080/     いま居る行だけ

しかも行の中の最初の1つだけなんだ。

a a  ↓ :s/a/Z/Z a          ← 2つ目の a は残る

行の中の全部を替えたいときは、末尾に g を足すよ。

:s/a/Z/gZ Z

g は global(全部)だね。これも sed と同じでしょう。

まとめておくね。

:s/A/B/      今の行の最初の1つ:s/A/B/g     今の行の全部

g を付けるかどうかが分かれ目だよ。忘れると1つしか変わらないので、結果を見て確かめる癖をつけてね。

05 / 08

:%s でファイル全部を置き換える

行を指定すると、範囲を選べるんだ。

:%s/A/B/g     ファイル全部:2,3s/A/B/    2行目から3行目:1,$s/A/B/    1行目から最後まで(% と同じ)

% は「全部の行」という印だよ。

:%s/80/8080/g

これがいちばんよく使う形だね。ファイル全体の 808080 に替えるんだ。

g の有無で結果が変わることに注意してね。

a aa a
打つもの結果
:%s/a/Z/Z a が2行(各行の最初だけ)
:%s/a/Z/gZ Z が2行(全部)

% は「どの行を」、g は「行の中のいくつを」なんだ。2つは別のことを言っているでしょう。

%    行の範囲g    行の中の範囲

ここを混ぜないようにしてね。両方要るときは両方付けるんだ。

範囲を絞る形も覚えておくと役に立つよ。

:2,3s/x/Y/     2〜3行目だけ:1,10s/x/Y/g   1〜10行目の全部
コメントの部分は替えたくない最初の10行は雛形なので触りたくない

替えたくない場所があるときに効くでしょう。sed でも同じことができるけれど、vi なら画面を見ながら決められるんだ。

最後に、いちばん大事なことを言っておくね。

> 置き換えたら、必ず確かめる

:%s/80/8080/g  ↓ 抜けてからgrep -c 8080 settei.confgrep -c '80$' settei.conf

替わった数と、残っていない数を見るんだ。まとめて替える命令は、やりすぎても気づきにくいでしょう。だから数で押さえるんだよ。

06 / 08

まとめて替えるのは危ない

:%s は強力だけれど、事故も大きいんだ。よくある失敗を見ておこうね。

:%s/80/8080/g

これ、8080 という文字が既にあったらどうなるかな。

port 8080  ↓ 80 が2か所ある(8080 の中)port 80808080

思わぬところが替わるでしょう。

もう1つの失敗も見てね。

:%s/log/LOG/g
log xdialog y      ← ここも替わる!

言葉の一部にも当たるんだ。grep で同じことに気をつけたのを覚えているかな(章5)。

守り方は3つあるよ。

1. まず grep で数を見る2. 狭い範囲で試す3. 控えを取ってから替える

1つ目はこうだね。

grep -c 80 settei.conf     いくつあるか先に数える

替わる数を先に知っておくでしょう。あとで grep -c 8080 が同じ数になれば、狙ったとおりだと分かるんだ。

2つ目はこうだよ。

:1,5s/80/8080/g    まず5行だけ(見る):%s/80/8080/g      よければ全部

小さく試して、広げるんだ。

3つ目はいつもの作法だね。

cp settei.conf settei.conf.bak

触る前に控えでしょう。

そして、失敗に気づいたときの逃げ道も持っておいてね。

u       直前の :%s を取り消す:q!     ぜんぶ捨てる

u:%s も戻せるよ。何百か所替えたものも1手で戻るんだ。

:%s/…/…/g で全部替わった  ↓ しまったu で全部戻る

保存する前なら助かるでしょう。だから :%s を打ったら、まず画面を見て、それから :wq という順番にしてね。慌てて :wq を打たないことが、いちばんの守りだよ。

07 / 08

grepsed との使い分け

ここまで来ると、同じことが2つの道具でできるようになったね。整理しておこうね。

grep -n port settei.conf     どの行にあるか一覧で見るvi の /port                  その行へ連れて行ってもらう
sed -i 's/80/8080/g' ファイル   まとめて替えるvi の :%s/80/8080/g            開いたまま替える

どちらでもできるでしょう。では、どう選ぶかというと。

見るだけ・一覧が欲しい    grep直しに行きたい            vi の /

grep全部を一度に見せてくれるんだ。

grep -n port settei.conf1:port 803:port 805:port 80

3か所あることが一目で分かるでしょう。そのあと vi1G 3G 5G と回ってもいいんだ。

grep で場所を知る → vi で直しに行く

2つを組み合わせるのが実務のやり方だよ。

置き換えのほうも同じだね。

全部替えていい・数が多い     sed -i選びたい・見ながら替えたい   vi

sed -i は速いけれど、替わった結果を見ていないでしょう。vi なら画面で確かめてから保存できるんだ。

sed -i    速い・戻せないvi        遅い・:q! で戻せる

取り返しがつくかどうかが違うんだよ。

だから、こう決めるといいよ。

大事なファイル・自信が無い   vi で見ながら使い捨て・自信がある         sed -i で一気に

慣れるまでは vi をおすすめするよ。:q! があるから、失敗が失敗にならないでしょう。

そして、あなたはもう両方持っているんだ。選べるということが強さだよ。1つしか知らないと、その道具でできることしかやらなくなってしまうからね。

08 / 08

これで vi は使える

まとめだよ。探して置き換えるがそろったね。

/語 n     下へ探す・次へ?語       上へ探す:s/A/B/   今の行:s/A/B/g  今の行の全部:%s/A/B/g ファイル全部:2,3s/…   行を絞る

中身で場所を見つけられるようになったでしょう。行番号を知らなくても直せるんだ。

この6回で、vi の全部が入ったよ。

1回目  出入り    Esc :q :q! :w :wq ZZ2回目  書く      i a I A o O3回目  動く      h j k l 0 $ w b gg G 3G4回目  消す      x dw D dd r cw u .5回目  写す      yy yw p P(dd p で動かす)6回目  探す      / ? n :s :%s

これだけで、現場の仕事は全部できるんだ。もっと便利な命令はあるけれど、無くても困らないものだよ。

いちばん大事なものを、もう一度書いておくね。

Esc      迷ったら押す:q!      何をしても元に戻るu        直前を取り消す

この3つがあるから、思いきって触れるでしょう。あなたはもう vi に閉じ込められないんだ。

次の回は腕試しだよ。

13章ぶんで覚えたものを、指示なしで組み合わせて解く

vi を開いて」とも「grep を使って」とも書いていない問題だよ。何をどう使うかは自分で決めるんだ。

ファイルを探す      find grep中身を見る          cat head less直す                vi動かす              chmod ./スクリプト確かめる            wc grep diff

全部あなたの道具でしょう。1章から積み上げてきたものを、最後に全部使うんだ。

解けたら、あなたはもう端末を怖がらなくていいよ。楽しみにしていてね。