today_rainy's blog

ガジェットやらプログラムやらを地道に弄くる。

シェルスクリプトの再勉強

そろそろcronに直書きするのも限界なので、シェルスクリプトの再勉強でもしますか。

例によって、下記のサイトを参考、というよりも自分用にまとめた結果です。
いつもありがとうございます。motw.mods.jp
シェルプログラミングの基礎知識

おまじない #!/bin/sh

スクリプトを実行するシェルプログラム(sh)を指定している。
あくまで直接実行した場合のみで、kshの引数でスクリプトを渡すと、おまじないは無視される。
実行結果をダンプするときは下記で出力してデバッグ

$ /bin/sh -xv test.sh

パーミッション設定

権限付与の仕方は[ugoa][+-=][rwx]。
 ugoa : 所有者-グループ-その他-全員
 +-= : 付与-削除-設定
 rwx : 読込-書込-実行

$ chmod u+x hello.sh

または、0(---),1(--x),2(-w-),3(-wx),4(r--),5(r-x),6(rw-),7(rwx)で各ユーザー毎に指定できる。

$ chmod 700 hello.sh

変数

基本は文字列として保存される。使う際には$を付けて$varのように使う。
変数を展開するときはダブルクォーテーション(")、
変数を展開しないときはシングルクォーテーション(')、
コマンドを実行して評価結果を得るには逆クォーテーション(`)
$0 スクリプトの名前
$1, $2, ..., $9 第1引数, 第2引数, ..., 第9引数
$# 与えられた引数の数
$* 与えられたすべての引数. 引数全体が"で囲まれている

計算式で使える演算子

計算したい式を$( (と) )で囲むと計算される。変数名の前に$はいらない。

x=5
y=10
z=$(( x + y ))

比較演算子 >,==,!=,<の結果は真なら1,偽なら0。ただし条件文に使えない。

コマンドを繋げる.

#command1,command2を順に実行
$ command1; command2
#command1が真ならcommand2を実行
$ command1 && command2
#command1が偽ならcommand2を実行
$ command1 || command2
#command1が真ならcommand2を、偽ならcommand3を実行
$ command1 && command2 || command3
#command1の標準出力をcommand2に渡す
$ command1 | command2

command1は後述の条件式にも変えることが可能。

条件式で使える演算子

条件式は[ と ]で囲む。否定は[ !と ] で囲む。[]の前後には空白がないとダメですよ。

数値の比較

 -eq(equal), -gt(greater than), -ge(greater than or equal), -lt(less than), -le(less than or equal), -ne(not equal)。

文字の比較

=,!=,-z(文字列の長さがzero)

その他

ディレクトリ・ファイルの有無 -e

制御構文

 if [ 条件 ]; then; 命令1; 命令2; 命令3; fi;
 if [ 条件1 ]; then; 命令1; elif [ 条件2 ]; 命令2; else; 命令3; fi;
case $変数 in
    パターン1)
        命令1
        ;;
    パターン2)
        命令2
        ;;
    パターン3|パターン4)
        命令3
        ;;
    *)
        命令4
        ;;
esac
for 変数 in アイテム1 アイテム2 ... アイテムN
do
    命令1
    命令2
    命令3
done
# for i in {1..10}やfor (( i = 0 ; i < 10 ; i++ ))のようにも書ける
while 条件文
do
  命令1
  命令2
  命令3
done
#ファイルを読み込むときの基本形 1行全体のときはセパレータを空白に。
while IFS='セパレーター' read -r field1 field2
do
    命令1
    命令2
    命令3
done < "ファイルのパス"

関数

こんな感じ。

#!/bin/sh

hello() { echo "Hello $1."; }

goodbye()
{
	echo "Goodbye $1."
	echo "Goodbye $2."
}

hello Taro
goodbye Taro Jiro

I/Oダイレクト

< 標準入力を読み込み
> 標準出力を書き込み
>> 標準出力を書き込み(追記)
2>> 標準エラー出力を書き込み(追記)

スクリプト内でよく使うコマンド

 basename
 dirname
 awk
 sed
 tee
 tr
 xargs