シェルスクリプトの変数は他言語のような厳密な型を持たず、基本的には文字列として扱われます。
ここでは変数の基本から、数値計算、bashの高度なパラメータ展開までを体系的にまとめています。
なお、環境変数や定数は大文字で表記し、ローカル変数は小文字(lower_case)にするのが一般的です。
変数の基本
変数は = で代入します。=の前後にスペースを入れるとエラーになります。
name="taro"
age="20"ダブルクォーテーション、もしくはシングルクォーテーションで値を囲んで代入すると、値にスペースを使うことができます。
name1="yamada taro"
name2='yamashita jiro'
echo $name1 # yamada taro
echo $name2 # yamashita jiroダブルクォーテーションとシングルクォーテーション、どちらを使うかはケースによって異なります。以下の場合どのように表示されると思いますか?
# 苗字
familyname="yamada"
# ダブルクォーテーション
name1="name1: $familyname taro"
# シングルクォーテーション
name2='name2: $familyname jiro'
echo $name1
echo $name2実行結果です。
name1: yamada taro
name2: $familyname jiroダブルクォーテーションで囲んだ方はfamilyname変数が展開されています。
一方シングルクォーテーションで囲んだ方は変数が展開されず「$familyname」とそのまま表示されています。
通常はダブルクォーテーションを使うケースが多いですが、値を厳密に扱いたいときはシングルクォーテーションで囲みます。
変数の参照
変数を参照するときは $ を付けます。
echo "$name"${}を使うと、変数名と隣接する文字が混ざるのを防げます。
試しに以下を実行してみます。
name="taro"
echo "name1: $name_san" # name_san という別の変数を探す
echo "name2: ${name}_san" # 正しく taro_san${}を付けた方はname変数を正しく参照しています。
name1:
name2: taro_san数値計算:$(( )) を使う
変数は文字列ですが、数値計算は $(( )) で行えます。
echo $((1 + 2)) # 3変数を使った計算も可能です。
x=10
y=3
echo $((x * y)) # 30この場合、$(( )) 内部のxとyには$を付けなくても大丈夫です。
※ $を付けても計算できます。
高度なパラメータ展開
高度なパラメータ展開は、変数の値を加工するためのミニ言語のようなものです。 外部コマンド無しで高速に文字列処理ができるため、非常に役立ちます。
以下では体系的にパラメータ展開を分類しています。
なお、実行例では変数値と変数を見やすく区別するため、変数を大文字で記載しています。
1.デフォルト値・代入・代替
デフォルト値(値を“返す”だけ。VARに代入しない)
| 構文 | VAR値あり | VAR未設定 | VAR空文字 |
|---|---|---|---|
| ${VAR:-default} | VARの値 | defaultを返す | defaultを返す |
| ${VAR-default} | VARの値 | defaultを返す | “”(空のまま) |
NAME="" # 空文字
NAME1=${NAME:-yamada}
echo "$NAME1" # yamada
echo "$NAME" # 空文字# NAME未設定
NAME2=${NAME-yamada}
echo "$NAME2" # yamada
echo "$NAME" # 空文字デフォルト値を“代入”する(値を返す+VARに代入)
| 構文 | VAR値あり | VAR未設定 | VAR空文字 |
|---|---|---|---|
| ${VAR:=default} | VARの値 | defaultを代入 | defaultを代入 |
| ${VAR=default} | VARの値 | defaultを代入 | “”(空のまま) |
NAME="suzuki" # 値あり
NAME3=${NAME:=yamada} # NAME変数に値があるため代入されない
echo "$NAME3" # suzuki
echo "$NAME" # suzukiNAME="" # 空文字
NAME3=${NAME:=yamada} # NAMEにyamadaが代入される
echo "$NAME3" # yamada
echo "$NAME" # yamadaNAME="" # 空文字
NAME4=${NAME=yamada} # NAMEは空文字
echo "$NAME4" # 空文字
echo "$NAME" # 空文字代替(設定されているかどうかで返す値を変える)
| 構文 | VAR値あり | VAR未設定 | VAR空文字 |
|---|---|---|---|
${VAR:+alt} | alt | “”(何も返さない) | “”(何も返さない) |
${VAR+alt} | alt | “”(何も返さない) | alt |
NAME="yamada"
NAME5=${NAME:+morita} # NAMEが設定されているので、NAME5変数の値はmoritaに代替される
echo "$NAME5" # morita
echo "$NAME" # yamadaNAME="" # 空文字
NAME6=${NAME:+morita} # NAMEが空文字なので何も返さない
echo "$NAME6" # 空文字
echo "$NAME" # 空文字NAME="" # 空文字
NAME6=${NAME+morita} # NAMEが空文字なので、NAME6変数の値はmoritaに代替される
echo "$NAME6" # morita
echo "$NAME" # 空文字2.文字列の長さ
VAR="hello"
echo "${#VAR}" # 53.部分文字列(スライス)
VAR="abcdef"
echo "${VAR:1}" # bcdef
echo "${VAR:1:3}" # bcd
echo "${VAR: -2}" # ef(「VAR:」と「-」の間にスペース必須)4.文字列の置換
| 書き方 | 動作 |
|---|---|
${VAR/pat/repl} | 最初の pat を repl に置換 |
${VAR//pat/repl} | すべて置換 |
${VAR/#pat/repl} | 先頭が pat なら置換 |
${VAR/%pat/repl} | 末尾が pat なら置換 |
PATH="/usr/bin:/usr/local/bin"
echo "${PATH/bin/BIN}" # /usr/BIN:/usr/local/bin
echo "${PATH//bin/BIN}" # /usr/BIN:/usr/local/BINFILE="photo.jpg"
echo "${FILE/#pho/toma}" # tomato.jpg
echo "${FILE/%.jpg/.png}" # photo.png以下の場合は対象文字列全体が置換されます。
VAR="abc123xyz"
echo "${VAR/*123*/FOUND}" # FOUND5.前方・後方の削除(パターンマッチ)
| 書き方 | 動作 |
|---|---|
${VAR#pat} | 先頭から最短一致を削除 |
${VAR##pat} | 先頭から最長一致を削除 |
${VAR%pat} | 末尾から最短一致を削除 |
${VAR%%pat} | 末尾から最長一致を削除 |
FILE="/home/user/home_photo.jpg"
echo "${FILE#/*home}" # /user/home_photo.jpg
echo "${FILE##/*home}" # _photo.jpg
echo "${FILE##*/}" # home_photo.jpg
echo "${FILE%home*}" # /home/user/
echo "${FILE%%home*}" # /
echo "${FILE%%.*}" # /home/user/home_photo6.変数名の展開(間接参照)
変数名を変数(間接参照)として扱います。
NAME="USER"
USER="taro"
echo "${!NAME}" # taro${!NAME} は NAME が指す先の変数(USER)を参照するので、結果は "taro" になります。

コメント