shプログラミング覚え書き
shって使いこなせばかなり便利だな。プログラミング言語としても面白い。(※注:Bourne Shell系のshell)
「The UNIX Programming Environment」の第5章の"SHELL PROGRAMMING"を読んでいる途中だが、 いろいろおさらいしときたいTIPSがある。
とありえず手元のMax OS XのGNU bashで、適当に動かしながら確認してみる。
setコマンド
単に
$ set
と打つと、今設定されている環境変数の一覧がでてくる。しかし、
$ set abcd
とうつと、なんと'abcd'を変数$1に格納してくれる。以降スペースを空けて渡された引数ごとに、$2、$3、$4・・と保存してくれる。
$ set aaa bbb ccc $ echo $1 aaa $ echo $2 bbb $ echo $3 ccc
「The UNIX Programming Environment」の中では、
$ set `date`
とdateコマンドの出力を$1, $2, ...変数に格納して、個別に取り出していた。 なるほど、便利だ。 awkを使っても同じことができるが、格段に短く記述できる。 例えば、時間”Wed Feb 18 21:30:45 JST 2015”の時刻だけ取り出したい場合
$ set `date` $ echo $4 21:31:53
とし、$4はそのままシェルスクリプトの中で、使い続けられる。 おなじことをawkでやろうと思うと、
$ time=`date | awk '{print $4}'` $ echo $time 21:31:53
とする。まあ、十分短いけれど。 その他のフィールドも、$1, $2 ...と使えるので、コマンドの一行結果の即時利用に関してはawkに比べて利便性が高い。
for文
shのfor文は強烈だ。構文は、
for var in command do ... done
だが、commmandの部分は、空白で区切られた文字列を返せば、何でもOKで、どんな長いコマンドでもOK。「The UNIX Programming Environment」の使用例で素晴らしいと思ったのは、sedとの組み合わせの例で、whichコマンドを実現しているスクリプト。 以下、command部だけ抜き出したような感じだが、
for i in `echo $PATH | sed 's/^:/.:/ s/::/:.:/ s/:$/:./ s/:/ /g'` do ・・・ done
上記は、PATHに入ってるディレクトリの羅列をスペースで区切るように変換している。PATHのディレクトリはコロン(:)で区切るがこれをスペースに変換している。その前に、PATHの中で空文字+コロンの場合は、カレントディレクトリを示すので、これをピリオドに置換している。(これが左端、中、右端の3パターン)と。 sedが置換作業を複数個同時に記述できる(改行が必要だが)のも素晴らしいが、それをそのままfor文に渡しているのに、まったく可読性がおちないところが素晴らしい。
そして、なんともまあcommandを省いた省略形も書ける。
for i do echo $i done
は、i には何も渡されてないように見えるが、これはシェルスクリプトにしたときに、
スクリプトに渡された引数が入る。たとえば、上記をtest.sh
に入れたとして、
$ test.sh 1 2 3 1 2 3
となる。 以前書いた記事 bundleプログラム改 - Programmer's Dialy で使っている。
case文
case文は簡易的な正規表現使えるところが強力だねえ。
以下のような適当なtest.sh
を書いたとする。
#!/bin/sh case $1 in data??.txt) echo "$1 is data";; esac
実行:
$ test.sh data01.txt data01.txt is data
表現的には
case $1 in data[0-9][0-9].txt) echo "$1 is data";; esac
あるいは、
case $1 in data*1.txt|data*2.txt) echo "$1 is data";; esac
も可。 最新のbashだともうちょっと正規表現の幅が広がってるんだろか。
以上。