「シェルスクリプトの基礎 - 変数」の版間の差分
(→数値の演算) |
|||
| 155行目: | 155行目: | ||
# 出力 | # 出力 | ||
300 | 300 | ||
<br> | |||
<source lang="sh"> | |||
#! /bin/bash | |||
VALUE1="100" | |||
VALUE2="200" | |||
expr "$VALE1" "+" "$VALUE2" | |||
# または | |||
expr $VALUE1 + $VALUE2 | |||
# または | |||
VALUE3=`expr "$str1" "+" "$str2"` | |||
echo "$VALUE3" | |||
</source> | |||
<br> | |||
# 出力 | |||
300 | |||
300 | |||
300 | |||
<br> | |||
整数の演算では、<code>expr</code>コマンドまたは<code>let</code>コマンドを使用するが、<br> | |||
実数を演算では、bcコマンドを使用する。<br> | |||
また、bcコマンドも制御構文を使用したスクリプト処理が可能である。<br> | |||
<source lang="sh"> | |||
#! /bin/bash | |||
VALUE1=10.5 | |||
VALUE2=3.2 | |||
echo $VALUE1 + $VALUE2 | bc | |||
ANS=`echo $VALUE1*$VALUE2 | bc` | |||
echo $ANS | |||
</source> | |||
<br> | <br> | ||
==== ランダムな数値の取得 ==== | ==== ランダムな数値の取得 ==== | ||
| 167行目: | 201行目: | ||
27591 | 27591 | ||
<br> | <br> | ||
== 文字列の連結 == | == 文字列の連結 == | ||
複数の変数を連結するには、以下のように続けて記述する。<br> | 複数の変数を連結するには、以下のように続けて記述する。<br> | ||
2020年11月8日 (日) 23:19時点における版
概要
変数の定義と参照
変数へ値を代入する時は$を付けず、変数を参照するときは$を付ける。
#!/bin/sh
name=Michael # 変数の定義
echo Hello $name # 変数の参照
echo "Hello $name" # ダブルクォーテーションは変数を展開する
echo 'Hello $name' # シングルクォーテーションは変数を展開しない
# 出力 Hello Michael Hello Michael Hello $name
未定義の変数を参照すると、空文字列と同様に扱われる。(エラーにはならない)
#!/bin/sh
echo "Hello $name !"
# 出力 Hello !
変数の内容の一部を取得する場合は、${変数名:開始位置:長さ}と指定する。
なお、先頭の開始位置は0である。
指定した文字列までを削除する場合、${変数名#文字列}と指定する。
文字列を後ろから削除する場合、${変数名%文字列}と指定する。
また、文字列の指定には、ワイルドカード*が使用できる。
以下の例では、(1)環境変数LANGの0文字目から5文字分のみ取得、(2).(ドット)文字までを削除、(3).(ドット)文字以降を削除を行っている。
なお、操作を指定せず${変数名}とする場合、$変数名と同義になる。
#! /bin/bash
echo "$LANG" # 環境変数LANGの内容を表示
echo "${LANG:0:5}" # (1) LANGの0文字目から5文字分のみ表示
echo "${LANG#*.}" # (2) .文字までを削除
echo "${LANG%.*}" # (3) .文字以降を削除
# 出力
ja_JP.utf8 # 環境変数LANGの内容
ja_JP # ${LANG:0:5}の結果
utf8 # ${LANG#*.}の結果
ja_JP # ${LANG%.*}の結果
下表に、主な変数の操作を示す。
| 指定方法 | 操作内容 |
|---|---|
| ${変数名:開始位置:長さ} | 開始位置から指定した長さ分の文字列を切り出す |
| ${変数名#パターン} ${変数名##パターン} |
パターン部分(前方一致)を削除する。 #の場合は最短一致、##の場合は最長一致となる。 |
| ${変数名%文字列} ${変数名%%文字列} |
パターン部分(後方一致)を削除する。 %の場合は最短一致、%%の場合は最長一致となる。 |
| ${変数名:-文字列} | 変数の内容を取得する。 変数がセットされていない場合、指定した文字列を返す。 |
| ${変数名:=文字列} | 変数の内容を取得する。 変数がセットされていない場合、指定した文字列を変数に代入して返す。 |
| ${#変数名} | 変数の文字数を取得する。(配列の場合は要素数) |
定数
以下のように実行すると、指定した変数や関数に対する代入、unsetができなくなる。
readonly var # 変数varをreadonlyにする
readonly -a arr # 配列arrをreadonlyにする
readonly -f func # 関数funcをreadonlyにする
以下のように、変数の定義と同時にreadonlyを指定することも可能である。
readonly USERNAME="Mike"
以下の例では、変数MAX_SIZEを100で初期化した後、200という値を代入しようとしている。
変数MAX_SIZEは定数化されているので、代入しようとした場合はエラーになる。
#!/bin/bash
readonly MAX_SIZE=100
MAX_SIZE=200
# 出力 ./sample.sh: 行 4: MAX_SIZE: 読み取り専用の変数です
変数の値の確認
testや[ ... ]で使用できる演算子には、以下のようなものがある。
- -z 文字列
- 文字列の長さが0の場合に真
- -n 文字列
- 文字列の長さが0でない場合に真
変数名にダブルクォーテーションを付けて値を展開して、上記の演算子でその文字列の長さをチェックすることにより、
変数に値が代入されている(または、代入されていない)ことを確認することができる。
変数に値が代入されていることを確認する
以下の例では、変数NAMEの値がセットされているか調べている。
#!/bin/bash
if [ -n "$NAME" ]; then
echo $NAME
fi
変数に値が代入されていないことを確認する
以下の例では、変数NAMEの値がセットされていないか調べている。
#!/bin/bash
if [ -z "$NAME" ]; then
echo 'NAME is not set'
fi
# 出力 NAME is not set
数値の演算
加算 / 減算
変数の値に対して、加算および減算を行うには以下のように記述する。
#!/bin/bash
val=100
let val=$val+200
echo $val
または
#!/bin/bash
val=100
val=$(($val+200))
echo $val
# 出力 300
#! /bin/bash
VALUE1="100"
VALUE2="200"
expr "$VALE1" "+" "$VALUE2"
# または
expr $VALUE1 + $VALUE2
# または
VALUE3=`expr "$str1" "+" "$str2"`
echo "$VALUE3"
# 出力 300 300 300
整数の演算では、exprコマンドまたはletコマンドを使用するが、
実数を演算では、bcコマンドを使用する。
また、bcコマンドも制御構文を使用したスクリプト処理が可能である。
#! /bin/bash
VALUE1=10.5
VALUE2=3.2
echo $VALUE1 + $VALUE2 | bc
ANS=`echo $VALUE1*$VALUE2 | bc`
echo $ANS
ランダムな数値の取得
Bashのシェル変数$RANDOMを参照すると、0~32767の範囲のランダムな整数を取得することができる。
#!/bin/bash
echo $RANDOM
# 出力 27591
文字列の連結
複数の変数を連結するには、以下のように続けて記述する。
#!/bin/sh
STR1="Shell script"
STR2="is intersting!"
STR=$STR1$STR2
echo $STR
また、以下のように変数を{}で括る。
#!/bin/sh
STR1="Shell script"
STR="${STR1} is intersting!!"
echo $STR
環境変数
以下の例では、環境変数SRC_ROOTが設定されているかを確認して、設定されていない場合はメッセージを出力して終了している。
echoの出力を>&2とリダイレクトすると、標準エラー出力へ出力できる。
#!/bin/bash
if [ -z $SRC_ROOT ]; then
echo 'Please set the "SRC_ROOT" environment variable and try again.' >&2
exit -1
fi
echo 'Program continues...'
# 出力
# 設定されている場合
Program continues...
# 設定されていない場合
Please set the "SRC_ROOT" environment variable and try again.
コマンドの実行結果を変数に代入する
ls、grep、find等のコマンドの実行結果を変数に代入するには、以下のように記述する。
変数=$(コマンド) または 変数=`コマンド`
以下の例では、lsコマンドの実行結果を変数FILESに代入して、echoで出力している。
#!/bin/sh
FILES=$(ls)
echo "$FILES"
または
#!/bin/sh
FILES=`ls`
echo "$FILES"
環境変数
以下の例では、環境変数SRC_ROOTが設定されているかを確認して、設定されていない場合はメッセージを出力して終了している。
echoの出力を>&2とリダイレクトすると、標準エラー出力へ出力できる。
#!/bin/bash
if [ -z $SRC_ROOT ]; then
echo 'Please set the "SRC_ROOT" environment variable and try again.' >&2
exit -1
fi
echo 'Program continues...'
# 出力
# 設定されている場合
Program continues...
# 設定されていない場合
Please set the "SRC_ROOT" environment variable and try again.
変数展開機能
変数展開の仕組みを利用すると、変数に格納された文字列を置換、変数の存在を確認、変数の初期値の指定等ができる。
パターン照合演算子
下表に示すように、変数展開の構文を使用すると、変数に格納された文字列の一部を置換した文字列を作成することができる。
また、パターン部分において、ワイルドカード(*、?、[a-z]等)が使用できる。
| 構文 | 意味 |
|---|---|
| ${変数/パターン/置換文字列} | パターンに一致する部分を置換文字列に置き換える(1つだけ) |
| ${変数//パターン/置換文字列} | パターンに一致する部分を置換文字列に置き換える(すべて) |
| ${変数#パターン} | 先頭から最短一致でパターンに一致する部分を取り除く |
| ${変数##パターン} | 先頭から最長一致でパターンに一致する部分を取り除く |
| ${変数%パターン} | 末尾から最短一致でパターンに一致する部分を取り除く |
| ${変数%%パターン} | 末尾から最長一致でパターンに一致する部分を取り除く |
- 最初に一致する文字列のみ置換する。
# 実行
X=aaabbbccc
Y=${X/b/B}
echo $Y
# 出力
aaaBbbccc
- パターンに一致する文字列を全て置換する。
# 実行
X=aaabbbccc
Y=${X//b/B}
echo $Y
# 出力
aaaBBBccc
sedコマンドと同様の結果を、シェルスクリプトの機能だけで実現できていることがわかる。
X=aaabbbccc
Y=$(echo $X | sed -e 's/bbb/BBB/g')
- フルパスからbasenameを取り出す。
- 以下の例では、/aaa/bbb/cccという絶対パスから、basenameのcccを抽出している。
- */というパターンで、先頭から最長一致させて、/aaa/bbb/を取り除いている。
# 実行
X=/aaa/bbb/ccc
Y=${X##*/}
echo $Y
# 出力
ccc
また、basenameを取得する場合、一般的に、basenameコマンドを使用した方が簡単である。
basename $X
- フルパスからdirnameを取り出す。
- 以下の例では、/aaa/bbb/cccという絶対パスから、ディレクトリ名の/aaa/bbbを抽出している。
- /*というパターンで、末尾から最短一致させて、/cccを取り除いている。
# 実行
X=/aaa/bbb/ccc
Y=${X%/*}
echo $Y
# 出力
/aaa/bbb
また、ディレクトリ名を取得する場合、一般的に、dirnameコマンドを使用した方が簡単である。
dirname $X
- '#'以降のコメントを削除する。
- #*というパターンで、末尾から最長一致させて、変数LINEの#以降の部分を削除している。
# 実行
LINE="aaa bbb # This is a comment"
LINE=${LINE%%#*}
echo $LINE
# 出力
aaa bbb
初期値
| 構文 | 意味 |
|---|---|
| ${変数:-word} | 変数が未定義の時、wordを返す。 |
| ${変数:=word} | 変数が未定義の時、変数にwordを代入して返す。 |
| ${変数:?} ${変数:?word} |
変数が未定義の時、エラーを表示する。 |
| ${変数:+word} | 変数が定義されている時、wordを返す。 |
- ${変数:-word}
- 例えば、
X=${COUNT:-0}と記述すると、変数Xの値は変数COUNTの値が無ければ0を返す。 - つまり、変数
COUNTの初期値を0とみなして参照する。 - この構文は、コマンドライン引数が省略された場合、初期値を設定するために使用できる。
- 例えば、
FILENAME=${1:-input.txt}とすると、変数FILENAMEの値は、第1パラメータで指定された値または初期値のinput.txtとなる。
- 例えば、
- ${変数:=word}
- 例えば、X=${COUNT:=0}と記述すると、変数COUNTの値が無ければ、変数Xおよび変数COUNTに0を代入する。
- ただし、変数に代入するため、コマンドライン引数や関数の引数の$1を参照する場合には、この方法は使用できない。
- ${変数:?word}
- 例えば、以下のように記述すると、変数COUNTの値が無ければエラーを出力して終了する。
# 実行
echo ${COUNT:?}
# 出力
-bash: count: パラメータが null または設定されていません
?の後ろに表示するメッセージを指定することもできる。
# 実行
echo ${COUNT:?パラメータが設定されていません}
# 出力
-bash: count: パラメータが設定されていません
- ${変数:+word}
- 変数に値が代入されている場合、代わりにwordの値を返す。
- 例えば、${COUNT:+1}は、変数COUNTが定義されていたら1と評価される。
# 実行
COUNT=9999
echo ${COUNT:+1}
# 出力
1
# 実行
COUNT=9999
unset COUNT
echo ${COUNT:+1}
# 出力
何も表示されない
位置指定で部分文字列を抽出する
| 構文 | 意味 |
|---|---|
| ${変数:offset} | offsetで指定した位置から末尾までの文字列を抽出する。 |
| ${変数:offset:length} | offsetで指定した位置からlength分の文字列を抽出する。 |
# 実行
HOGE=ABCDEFGHIJ
echo ${HOGE:3}
# 出力
DEFGHIJ
# 実行
HOGE=ABCDEFGHIJ
echo ${HOGE:3:4}
# 出力
DEFG
offsetやlength に負の値を指定して、末尾から文字列を抽出することもできる。
ただし、offsetの前に1つ以上のスペースが必要である。(スペースを入れないと、${変数:-word}という形で初期値が指定されたとみなされる)
# 実行
HOGE=ABCDEFGHIJ
echo ${HOGE: -3}
# 出力
HIJ
# 実行
HOGE=ABCDEFGHIJ
echo ${HOGE: -5:-2}
# 出力
FGH