tands_bの日記

技術メモ。大したことは書きません

【bash】特殊変数・汎用構文

制御シェルの種類

 sourceを用いる方法と直接シェルスクリプトを用いる方法で制御するシェルが異なる。

実行方法 特徴
source ログインセッションの一部であるかのように通常シェルで実行される。
sh or スクリプト指定 シェルスクリプトの中から呼び出されるコマンドはサブシェルとして実行され、完了すると制御を親シェルに戻す。親とサブシェルに別れることで、環境変数を分けるなど有効な使用方法があるらしい。

特殊変数

変数名 内容
$* 全ての位置パラメータを保持する変数。""で囲んだ場合、全ての位置パラメータの外側を""で括った値になる。
[例]:$ sample.sh s1 s2 ⇨ "s1 s2"
$@ 全ての位置パラメータを保持する変数。""で囲んだ場合、各位置パラメータを""で括った値になる。
[例]:$ sample.sh s1 s2 ⇨ "s1" "s2"
$0 スクリプト名。
$# 位置パラメータの数。
[例]:sample.sh s1 s2 ⇨ 2
$? 直前に実行されたコマンドの終了ステータス。正常終了の場合は0、異常終了の場合は0以外(1が警告、2がエラーのことが多い)。
$! バックグラウンドで実行されたコマンドのプロセスID。
$$ コマンド自身のPID。

汎用構文

構文 内容
${} 変数名を区切るために使用される構文。例えば10番目以降の引数を用いる場合、変数の後ろに文字列を続けたい場合、可読性をあげたい場合に使用される。
echo "${10}"
echo "${var}_sample"
$() 括弧内のコマンドを実行して結果を返す構文。バッククォート(`)で括るのと結果は同じだが、ネスト可能・可読性高いという理由でこちらの構文を使用する方が好ましい。
$(()) 括弧内の算術演算を行う構文。

文字列演算子の構文

構文 内容 備考
${#var} 変数の値の長さを文字列で返す。
[例]:
var="sample"
echo "${#sample}" ⇨ 6が表示される。
-
${var:-word} 変数varが存在し、かつnullでない場合にその値を返す。それ以外の場合はwordを返却する。
[例]:
echo ${var:-sample} ⇨ sample
-
${var:=word} 変数varが存在し、かつnullでない場合にその値を返す。それ以外の場合、varにwordを代入する。ただし、位置パラメータや特殊パラメータは使用できない。
[例]:
echo ${var:=sample} ⇨ sampleが表示される
echo $var ⇨ sampleが表示される。
-
${var:?message} 変数varが存在し、かつnullでない場合にその値を返す。それ以外の場合、messageを出力してコマンドあるいはスクリプトを中止する。 -
${var:+word} 変数varが存在し、かつnullでない場合にwordを返す。それ以外の場合、nullを返す。 -
${var:offset:length} 変数varの値から、offsetの位置からlength数の長さの部分文字列を取り出す。varが@の場合、offsetを先頭とする位置パラメータの番号となる。
[例]:
var="sample"
echo "${var:2:2}" ⇨ mpが表示される。
-
${var#pattern} 変数varの値の始めの部分とpatternが一致した場合、最初に一致した部分を削除して残りの値を返す。
[例]:
var="/Users/tands_b/sample.tar.gz"
echo "${var#/*/}" ⇨ tands_b/sample.tar.gzが表示される。
パターンに使用できるワイルドカードは*, ?, []
${var##pattern} 変数varの値の始めの部分とpatternが一致した場合、最初からパターンの一致が終わるまでを削除して残りの値を返す。
[例]:
var="/Users/tands_b/sample.tar.gz"
echo "${var##/*/}" ⇨ sample.tar.gzが表示される。
同上
${var%pattern} 変数varの値の終わりの部分とpatternが一致した場合、最初にパターンが一致した部分を削除して残りの値を返す。
[例]:
var="/Users/tands_b/sample.tar.gz"
echo "${var%.*}" ⇨ /Users/tands_b/sample.tarが表示される。
同上
${var%%pattern} 変数varの値の終わりの部分とpatternが一致した場合、最後からパターンが一致した部分を削除して残りの値を返す。
[例]:
var="/Users/tands_b/sample.tar.gz"
echo "${var%%.*}" ⇨ /Users/tands_b/sampleが表示される。
同上
${var/pattern/string} 変数varの値で最初にpatternと一致した部分がstringに置換された値を返す。
[例]:
var="/Users/tands_b/sample.tar.gz
echo "${var/\/*\//\~/}" ⇨ ~/sample.tar.gzが表示される。
同上
${var//pattern/string} 変数varの値でpatternと一致した部分が全てstringに置換された値を返す。 同上

文字列演算子の活用

 擬似履歴機能を持ったcdコマンドを実装できる。通常cd, cd - では一回分の移動しか記憶できない。

# cd の代わり。メモリに移動先をスタックする。
function pushd()
{
  local dirname="${1:-${HOME}}"
  if [ ! -e "$dirname" ]; then
    echo "$dirname: No such file or directory"
    return 1
  fi

  if [ "${dirname:0:1}" != "/" ]; then
    dirname="${DIR_STACK%% *}/${dirname}"
  fi

  DIR_STACK="$dirname ${DIR_STACK:-$PWD}"
  cd ${dirname:?"missing directory name."}
}

# cd - の代わり。 メモリにスタックされた階層をポップする。
function popd()
{
  DIR_STACK="${DIR_STACK#* }"
  cd "${DIR_STACK%% *}"
  echo $PWD
}