「シェルスクリプトの基礎 - 変数」の版間の差分
| 166行目: | 166行目: | ||
FILES=`ls` | FILES=`ls` | ||
echo "$FILES" | echo "$FILES" | ||
</source> | |||
<br><br> | |||
== 変数展開機能 == | |||
変数展開の仕組みを利用すると、変数に格納された文字列を置換、変数の存在を確認、変数の初期値の指定等ができる。<br> | |||
<br> | |||
==== パターン照合演算子 ==== | |||
下表に示すように、変数展開の構文を使用すると、変数に格納された文字列の一部を置換した文字列を作成することができる。<br> | |||
また、パターン部分において、ワイルドカード(*、?、[a-z]等)が使用できる。<br> | |||
<center> | |||
{| class="wikitable" | |||
|- | |||
! 構文 !! 意味 | |||
|- | |||
| ${変数/パターン/置換文字列} || パターンに一致する部分を置換文字列に置き換える(1つだけ) | |||
|- | |||
| ${変数//パターン/置換文字列} || パターンに一致する部分を置換文字列に置き換える(すべて) | |||
|- | |||
| ${変数#パターン} || 先頭から最短一致でパターンに一致する部分を取り除く | |||
|- | |||
| ${変数##パターン} || 先頭から最長一致でパターンに一致する部分を取り除く | |||
|- | |||
| ${変数%パターン} || 末尾から最短一致でパターンに一致する部分を取り除く | |||
|- | |||
| ${変数%%パターン} || 末尾から最長一致でパターンに一致する部分を取り除く | |||
|} | |||
</center> | |||
<br> | |||
* 最初に一致する文字列のみ置換する。 | |||
<source lang="sh"> | |||
# 実行 | |||
X=aaabbbccc | |||
Y=${X/b/B} | |||
echo $Y | |||
# 出力 | |||
aaaBbbccc | |||
</source> | |||
<br> | |||
* パターンに一致する文字列を全て置換する。 | |||
<source lang="sh"> | |||
# 実行 | |||
X=aaabbbccc | |||
Y=${X//b/B} | |||
echo $Y | |||
# 出力 | |||
aaaBBBccc | |||
</source> | |||
<br> | |||
sedコマンドと同様の結果を、シェルスクリプトの機能だけで実現できていることがわかる。<br> | |||
<source lang="sh"> | |||
X=aaabbbccc | |||
Y=$(echo $X | sed -e 's/bbb/BBB/g') | |||
</source> | |||
<br> | |||
* フルパスからbasenameを取り出す。 | |||
*: 以下の例では、/aaa/bbb/cccという絶対パスから、basenameのcccを抽出している。 | |||
*: */というパターンで、先頭から最長一致させて、/aaa/bbb/を取り除いている。 | |||
<source lang="sh"> | |||
# 実行 | |||
X=/aaa/bbb/ccc | |||
Y=${X##*/} | |||
echo $Y | |||
# 出力 | |||
ccc | |||
</source> | |||
<br> | |||
また、basenameを取得する場合、一般的に、basenameコマンドを使用した方が簡単である。<br> | |||
<source lang="sh"> | |||
basename $X | |||
</source> | |||
<br> | |||
* フルパスからdirnameを取り出す。 | |||
*: 以下の例では、/aaa/bbb/cccという絶対パスから、ディレクトリ名の/aaa/bbbを抽出している。 | |||
*: /*というパターンで、末尾から最短一致させて、/cccを取り除いている。 | |||
<source lang="sh"> | |||
# 実行 | |||
X=/aaa/bbb/ccc | |||
Y=${X%/*} | |||
echo $Y | |||
# 出力 | |||
/aaa/bbb | |||
</source> | |||
<br> | |||
また、ディレクトリ名を取得する場合、一般的に、dirnameコマンドを使用した方が簡単である。<br> | |||
<source lang="sh"> | |||
dirname $X | |||
</source> | |||
<br> | |||
* '#'以降のコメントを削除する。 | |||
*: #*というパターンで、末尾から最長一致させて、変数LINEの#以降の部分を削除している。 | |||
<source lang="sh"> | |||
# 実行 | |||
LINE="aaa bbb # This is a comment" | |||
LINE=${LINE%%#*} | |||
echo $LINE | |||
# 出力 | |||
aaa bbb | |||
</source> | |||
<br> | |||
==== 初期値 ==== | |||
<center> | |||
{| class="wikitable" | |||
|- | |||
! 構文 !! 意味 | |||
|- | |||
| ${変数:-word} || 変数が未定義の時、wordを返す。 | |||
|- | |||
| ${変数:=word} || 変数が未定義の時、変数にwordを代入して返す。 | |||
|- | |||
| ${変数:?}<br>${変数:?word} || 変数が未定義の時、エラーを表示する。 | |||
|- | |||
| ${変数:+word} || 変数が定義されている時、wordを返す。 | |||
|} | |||
</center> | |||
* ${変数:-word} | |||
*: 例えば、<code>X=${COUNT:-0}</code>と記述すると、変数<code>X</code>の値は変数<code>COUNT</code>の値が無ければ0を返す。 | |||
*: つまり、変数<code>COUNT</code>の初期値を0とみなして参照する。 | |||
*: <br> | |||
*: この構文は、コマンドライン引数が省略された場合、初期値を設定するために使用できる。 | |||
*: 例えば、<code>FILENAME=${1:-input.txt}</code>とすると、変数<code>FILENAME</code>の値は、第1パラメータで指定された値または初期値のinput.txtとなる。 | |||
<br> | |||
* ${変数:=word} | |||
*: 例えば、X=${COUNT:=0}と記述すると、変数COUNTの値が無ければ、変数Xおよび変数COUNTに0を代入する。 | |||
*: ただし、変数に代入するため、コマンドライン引数や関数の引数の$1を参照する場合には、この方法は使用できない。 | |||
<br> | |||
* ${変数:?word} | |||
*: 例えば、以下のように記述すると、変数COUNTの値が無ければエラーを出力して終了する。 | |||
<source lang="sh"> | |||
# 実行 | |||
echo ${COUNT:?} | |||
# 出力 | |||
-bash: count: パラメータが null または設定されていません | |||
</source> | |||
<br> | |||
?の後ろに表示するメッセージを指定することもできる。<br> | |||
<source lang="sh"> | |||
# 実行 | |||
echo ${COUNT:?パラメータが設定されていません} | |||
# 出力 | |||
-bash: count: パラメータが設定されていません | |||
</source> | |||
<br> | |||
* ${変数:+word} | |||
*: 変数に値が代入されている場合、代わりにwordの値を返す。 | |||
*: 例えば、${COUNT:+1}は、変数COUNTが定義されていたら1と評価される。 | |||
<source lang="sh"> | |||
# 実行 | |||
COUNT=9999 | |||
echo ${COUNT:+1} | |||
# 出力 | |||
1 | |||
</source> | |||
<br> | |||
<source lang="sh"> | |||
# 実行 | |||
COUNT=9999 | |||
unset COUNT | |||
echo ${COUNT:+1} | |||
# 出力 | |||
何も表示されない | |||
</source> | |||
<br> | |||
==== 位置指定で部分文字列を抽出する ==== | |||
<center> | |||
{| class="wikitable" | |||
|- | |||
! 構文 !! 意味 | |||
|- | |||
| ${変数:offset} || offsetで指定した位置から末尾までの文字列を抽出する。 | |||
|- | |||
| ${変数:offset:length} || offsetで指定した位置からlength分の文字列を抽出する。 | |||
|} | |||
</center> | |||
<br> | |||
<source lang="sh"> | |||
# 実行 | |||
HOGE=ABCDEFGHIJ | |||
echo ${HOGE:3} | |||
# 出力 | |||
DEFGHIJ | |||
</source> | |||
<br> | |||
<source lang="sh"> | |||
# 実行 | |||
HOGE=ABCDEFGHIJ | |||
echo ${HOGE:3:4} | |||
# 出力 | |||
DEFG | |||
</source> | |||
<br> | |||
offsetやlength に負の値を指定して、末尾から文字列を抽出することもできる。<br> | |||
ただし、offsetの前に1つ以上のスペースが必要である。(スペースを入れないと、${変数:-word}という形で初期値が指定されたとみなされる)<br> | |||
<source lang="sh"> | |||
# 実行 | |||
HOGE=ABCDEFGHIJ | |||
echo ${HOGE: -3} | |||
# 出力 | |||
HIJ | |||
</source> | |||
<br> | |||
<source lang="sh> | |||
# 実行 | |||
HOGE=ABCDEFGHIJ | |||
echo ${HOGE: -5:-2} | |||
# 出力 | |||
FGH | |||
</source> | </source> | ||
<br><br> | <br><br> | ||
2020年10月6日 (火) 14:32時点における版
概要
変数の定義と参照
変数へ値を代入する時は$を付けず、変数を参照するときは$を付ける。
#!/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 !
定数
以下のように実行すると、指定した変数や関数に対する代入、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
ランダムな数値の取得
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
コマンドの実行結果を変数に代入する
ls、grep、find等のコマンドの実行結果を変数に代入するには、以下のように記述する。
変数=$(コマンド) または 変数=`コマンド`
以下の例では、lsコマンドの実行結果を変数FILESに代入して、echoで出力している。
#!/bin/sh
FILES=$(ls)
echo "$FILES"
または
#!/bin/sh
FILES=`ls`
echo "$FILES"
変数展開機能
変数展開の仕組みを利用すると、変数に格納された文字列を置換、変数の存在を確認、変数の初期値の指定等ができる。
パターン照合演算子
下表に示すように、変数展開の構文を使用すると、変数に格納された文字列の一部を置換した文字列を作成することができる。
また、パターン部分において、ワイルドカード(*、?、[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