シェルスクリプト in bash

前置き

bashシェルスクリプトの基本文法をまとめます。

本文

変数

  • 組み込みシェル変数
HOME      ホームディレクトリ。
USER      ユーザ名。
HOSTNAME  ホスト名。
LANG      ロケール(LC_ALLなどが無いときに有効)。
PATH      コマンド検索パス。
PS1       プロンプト。
PPID      親プロセスのPID。
PWD       カレントディレクトリ。
ID        ユーザID。
  • 特殊変数
$n  コマンドライン引数。nは数字。$0はスクリプト名。2桁なら${10}のように参照。shiftでずれる。
$#  引数の個数。
$*  全引数のリスト。"$*"とすると1つの文字列に連結。
$@  全引数のリスト。"$@"とすると文字列のリスト。
$?  直前のコマンドの終了コード。
$!  最後に実行したバックグラウンドジョブのPID。
$$  実行中シェルのPID。
$-  現在のオプションフラグ(set -oと連動)。
  • 変数展開
echo ${var:-default_value}         # varが未初期化ならdefault_valueで代替。
echo ${var:=default_value}         # varが未初期化ならdefault_valueで初期化。
echo ${var:?unset}                 # varが未初期化なら var: unset と表示してスクリプト終了。

var=/path/to/file.txt
echo ${#var}                       # 文字列長に展開。
                                   # 17
echo ${var#/*/}                    # 最初の最短部分マッチを削除。
                                   # to/file.txt
echo ${var##/*/}                   # 最初の最長部分マッチを削除。
                                   # file.txt
echo ${var%txt}                    # 最後の最短部分マッチを削除。
                                   # /path/to/file.
echo ${var%%[!/]*txt}              # 最後の最長マッチ部分を削除。
                                   # /
echo ${var/txt/html}               # 最初の最長マッチを置換。
                                   # /path/to/file.html
echo ${var//t/T}                   # 全ての最長マッチを置換。
                                   # /paTh/To/file.TxT
echo ${var////:}                   # :path:to:file.txt

var=1
echo $((var+3))                    # 演算結果に展開。
                                   # 4

制御構造

  • if文
if test -a ~/bin/foo    # testの代わりに、[ -a ~/bin/foo ] と書いても可。
then
  echo foo: exists
elif [ -d ~/bin ]
then
  echo tmp: is a directory
else
  echo huh?
fi                      # if、then、elif、else、fi、それぞれ別々の行に書く。
  • for文
for var in a b c        # in以降を省略すると、in $@ と解釈される。
do
  echo $var
done
for var in *.txt
do
  echo $var
done
IFS=:                   # Internal Field Separator(組み込み変数)。
for var in $PATH
do
  echo $var
done
  • case文
case $# in
  1)
    echo $1
    ;;
  2)
    echo $1 $2
    ;;
  *)
    echo usage: foo p1 p2
    ;;
esac
  • while文
gen=1
while [ -a foo.$(printf "%03d" $gen) ]
do
  echo $gen: exists
  gen=`expr $gen + 1`
done
  • until文
gen=1
until [ $gen -ge 10 ]
do
  touch foo.$(printf "%03d" $gen)
  gen=`expr $gen + 1`
done
  • select文
PS3='Input a number: '
select var in Yes No Keep
do
  echo $REPLY           # 入力された数値(組み込み変数)。
  if [ $var = "Keep" ]; then continue; fi
  if [ $var = "No" ]; then break; fi
done                    # breakするまで繰り返す。
  • 1行で書く
 if [ -a /etc ]; then echo etc: exists; fi
 until ping 192.168.1.111 -c 1; do sleep 30; done

条件式

  • 文字列
if [ -n $1 ]; then echo $1: not empty; fi
if [ -z $1 ]; then echo $1: empty; fi
if [ $1 = "quit" ]; then echo quit; fi    # ==でも可(たぶん)。
if [ $1 != "quit" ]; then echo $1: not quit; fi
  • 数値
if [ $1 -eq 10 ]; then echo 10; fi
if [ $1 -ne 10 ]; then echo not 10; fi
if [ $1 -ge 10 ]; then echo ">= 10"; fi
if [ $1 -gt 10 ]; then echo "> 10"; fi
if [ $1 -le 10 ]; then echo "<= 10"; fi
if [ $1 -lt 10 ]; then echo "< 10"; fi
  • ファイル属性
-d  ディレクトリ
-e  存在する(-aでも可)
-f  通常のファイル
-h  シンボリック・リンク(-Lでも可)
-N  最後に読み取られてから修正されている
-O  現ユーザが所有
-p  名前付きのパイプ
-r  現ユーザが読み取り可
-s  空ではない
-S  ソケット
-w  現ユーザが書き込み可
-x  現ユーザが実行可
-nt 更新日時が新しい(2つのファイルを比較)
-ot 更新日時が新しい(2つのファイルを比較)
-ef iノード番号が等しい(2つのファイルを比較)
  • 論理演算
if [ $1 -ge 0 -a $1 -lt 10 ]; then echo $1: 1-digit; fi
if [ $1 -lt 0 -o $1 -ge 10 ]; then echo $1: 1-digit; fi
if [ ! -e foo.txt ]; then echo $1: not exist; fi

関数

function usage          # function usage の代わりに usage() でも可。
{
  echo "usage: foo [OPTIONS] FILENAME..."
}
cat3()                  # ()の中に引数リストは書かない。
{
  echo $1 $2 $3
}

usage                   # 呼び出し。
cat3 foo bar buz
>>
Last modified:2010/06/11 18:01:46
Keyword(s):
References:[サーバ管理・Linux関連]
This page is frozen.