2018年10月
  1 2 3 4 5 6
7 8 9 10 11 12 13
14 15 16 17 18 19 20
21 22 23 24 25 26 27
28 29 30 31      

Amazonウィジェット

  • お気に入り
  • 書籍ランキング

AdSense

  • 広告
無料ブログはココログ

« C# System.Windows.Mediaの追加方法。 | トップページ | Arduinoのイーサネットシールドを使う »

2018年7月20日 (金)

シェルスクリプトのコツ

 シェルスクリプトを覚えると便利なことはわかっているが、ネットに書いてあるコマンドを書き写してもなかなかうまく実行できなかった。それにグラフィックや音声など、派手なことはできないので、なかなか学ぶモチベーションの上がらない分野だった。ところがある本をきっかけにシェルスクリプト感が一変する。

シェルの考え方がわかれば、そんなに躓かなくなる。

シェルスクリプトでは、実はifや[括弧]もすべてコマンドである。だから、

if [ $hoge = $name ]; then

などのように、スペースを空ける。


値を入れるときはスペースを空けない。

hoge="hello world"
huga=234

もしスペースを空けてしまうと、そんなコマンドがないとか怒られてしまう。

huga = 234

こう書くと、234というコマンドか、hugaというコマンドに=と234という引数が渡されているように見える。

最初からスクリプトを書かず、一行で実行できることを色々試してみるのがおすすめ。
大抵のことは一行で済ませられるので、大々的にスクリプトを書くのはforとかwhileが活用できるようになってからでも遅くない。


HPやブログに書いてある内容を写経するのはあまりお勧めできない。というのは、
コピペといえど変な記号が混じってしまう。手で打てばいいといっても、今度はエルと数字のイチを間違えて、そんなオプションないとか、そんなコマンドない。などと怒られる。
スペース一個、オプション一個で簡単にエラーが出てしまうので、とにかく罠が多いのだ。エラーもそっけないし、大抵は英語だ。


最初からやりたいことを実現しようとせず、まずはシェルの世界を体感するのがいい。
適当なデータを加工してみて、自分で「じゃあこうしたらこんなことができるか?」という発想を得られるまで試してみる事。思いついたことを何も見ずに書けるようになることが体感期間終了の目安。


適当なデータはlinuxのログとか、その辺のwebのテキストデータでも何でもいい。
こういう練習用データを使って試しているうちに、シェルのコツが身につく。
(練習用データを探しているうちに別なことに興味が移ってしまうことは意外と多い。)


例えば、netstatの出力から、特定のアドレスの行だけをリストにするとか、
あるポート番号を使っているアプリの名前を出すとか。




ためしにlsコマンドを使って、同じ拡張子のファイルに対してファイル名を一括変換するツールを書いてみよう。


練習用のディレクトリを作って、その中になにか適当なファイルを用意してみよう。

echo "hello" > $RANDOM.txt

と打つと、一回実行するごとに、乱数で作ったファイル名を持ったテキストファイルができる。

これをforで繰り返してみよう。
さてCでは
for(int i=0;i<10;i++)

のように書けるが、シェルスクリプトでは
for i in `seq 10`

のように書き始める。


この書き方のベースはpythonの
for i in range(10):
に非常によく似ている。


range(10)に当たる部分がちょうど
`seq 10`

と対応していて、実はseq 10というのはコマンドとその引数。
そのまま

seq 10
と打ち込んでみよう。1から10の数字が一行ずつ出てきたはずである。
この実行結果を``でくくると、コマンド実行結果をfor文に渡せる。


代わりに例えば、

`ls -1 *.txt`
などとすれば、テキストファイルのリストから一個ずつファイル名を取り出せるというわけ。


for i
となっているので、変数iに`seq 10`からの値が一個ずつ入る。


先ほどの乱数でファイルを作るコマンドを入れて、これらの要素を数珠繋ぎにすれば、
for i in `seq 10`; do echo "hello" > $RANDOM.txt; done

とすることができる。
これを実行すると、乱数で作ったファイル名のテキストが10個できる。



次にちょっと実用例

lsコマンドは、出力を一行に一項目で出すためのオプションがある。まずはこれを最初に実行してみよう。
それをみてから、次にパイプでくっつけるものを考える。


ls -1 *.txt | while read line; do echo $line; done


これを実行するとls -1 *.txtの結果と変わらないが、
ファイル名を編集しようと、文字列を追加することもできる。


ls -1 *.txt | while read line; do echo aho_$line; done
aho_16144.txt
aho_18738.txt
aho_18857.txt
aho_20865.txt
aho_23939.txt
:


文字列を加工すればコマンドも実行できるはず。
いきなりやると失敗するので、まずはエコーで様子を見て、

ls -1 *.txt | while read line; do echo "mv $line aho_$line"; done
mv 16144.txt aho_16144.txt
mv 18738.txt aho_18738.txt
mv 18857.txt aho_18857.txt
mv 20865.txt aho_20865.txt
mv 23939.txt aho_23939.txt
:


問題なければ、その文字列をそのままコマンドとして実行する。
これにはevalコマンドを使う。
さっきechoだったところをevalに書き換えるだけで簡単。


ls -1 *.txt | while read line; do eval "mv $line aho_$line"; done


こうすれば安全に、やりたいことを確実に実行できるというわけ。




次回に続く。

« C# System.Windows.Mediaの追加方法。 | トップページ | Arduinoのイーサネットシールドを使う »

Linux」カテゴリの記事

コメント

コメントを書く

(ウェブ上には掲載しません)

トラックバック

この記事のトラックバックURL:
http://app.cocolog-nifty.com/t/trackback/518723/66960244

この記事へのトラックバック一覧です: シェルスクリプトのコツ:

« C# System.Windows.Mediaの追加方法。 | トップページ | Arduinoのイーサネットシールドを使う »