Linux講座にようこそ。このページは「Linuxの使い方 - 第6章 シェルスクリプトの作り方」です。

Linuxの使い方

6. シェルスクリプトの作り方(2/8)

6.3 シェル変数と文字列演算

シェル変数とは値を格納する領域のことで、これを使うことにより、より高度なシェルスクリプトを作ることが出来ます。シェル変数には次の3種類があります。

ユーザ定義変数
ユーザが必要に応じて作成できる変数で、自由に名前を付けることが出来ますし、値の参照・設定も自由に行うことが出来ます。
位置パラメータ
シェルが用意する変数で、名前は1〜nまでの数字と決まっています。シェルスクリプト実行時に指定した引数の値を持っています。また、setコマンドで値の設定を行うことも出来ます。
環境変数
シェルやアプリケーションソフトにより作成される変数で、名前は大文字のものがほとんどです。どのような環境変数があるかは「環境変数」をご覧ください。

ユーザ定義変数の名前は先頭1文字が英字で、2文字目以降は英数字の組み合わせです。なお、_(アンダライン)は英字に含みます。

6.3.1 変数への値の代入と参照

ユーザ定義変数と環境変数に値を設定するには前で説明したreadコマンドで入力するか、=演算子で代入します。また、位置パラメータに直接値を設定するにはsetコマンドの引数に値を指定します。

変数の値を参照するには${変数名}$変数名のどちらの形式でも可能ですが、シェルが変数名を認識できない場合は${変数名}の形式を使用します。(具体的な使用例は「文字列の連結」をご覧ください)また、位置パラメータの1〜9までは$数字の形式で参照できますが、10以上は${10}のような指定になります。

また、ユーザ定義変数の消去(開放)はunsetコマンドで行います。なお、以降、ユーザ定義変数は単に変数と記述します。

※変数への値の設定
変数=値 ← =の前後に空白を置いてはいけません。また、値として空白文字を含む場合は'(アポストロフィ)または、"(引用符)で括ります

※位置パラメータへの値の設定
set 値1 値2 … ← 位置パラメータ1には「値1」が、位置パラメータ2には「値2」が設定されます

※値の参照
${変数名}
$変数名
${n} ← nは数字です
$n ← nは1~9の数字です

※変数の消去(開放)
unset 変数名

変数に設定されている文字列を文字列演算子を使って、次のような操作を行うことが出来ます。

また、変数の値に文字列を連結して文字列を作ることが出来ます。

デフォルト値の設定

【表6-4】デフォルト値の設定演算子一覧
形式説明/例題
${変数名:-語}変数が存在し、値が設定されている場合はその値を返し、それ以外の場合は「語」を返します。
$ var1="Hello" ← 変数var1へ値を設定します
$ rtn=${var1:-"World"} ← 戻り値を変数rtnに代入します
$ echo $rtn ← 戻り値を表示します
Hello
$ unset var1 ← 変数var1を消去します
$ rtn=${var1:-"World"}
$ echo $rtn ← 戻り値を表示します
World
$ echo $var1
 ← 変数var1は存在しないため空行です
$
${変数名:=語}変数が存在し、値が設定されている場合はその値を返し、それ以外の場合は変数に「語」を設定します。(位置パラメータは不可)
$ unset var1
$ rtn=${var1:="World"}
$ echo $rtn ← 戻り値を表示します
World
$ echo $var1 ← 変数var1の値を表示します
World
$
${変数名:+語}変数が存在し、値が設定されている場合は「語」を返し、それ以外の場合は空(NULL)を返します。
$ var1="Hello"
$ rtn=${var1:+"True"}
$ echo $rtn
True ← 戻り値です
$ unset var1
$ rtn=${var1:+"True"}
$ echo $rtn
 ← 戻り値は空(NULL)です
$

値が設定されていなかったときのエラー処理

【表6-5】エラー処理演算子一覧
形式説明/例題
${変数名:?メッセージ} 変数が存在し、値が設定されている場合はその値を返し、それ以外の場合は「メッセージ」を出力します。次の例題のシェルスクリプト(ex10.sh)は、引数が指定されなかった場合はメッセージを出力して直ちに終了します。
#!/bin/bash
# 機能  :  引数の有無をチェックします
# 作成  :  メリー
 
para=${1:?"引数の指定がありません"}    # 引数の有無をチェック
 
echo "引数は${para}です"
$ ex10.sh ← 引数指定無しで実行します
/home/merry/mybin/ex10.sh: 行 5: 1: 引数の指定がありません
$
$ ex10.sh Hello ← 引数を指定して実行します
引数はHelloです
$

文字列の部分取り出し

【表6-6】部分取り出し演算子一覧
形式説明/例題
${変数名:位置:長さ}
${変数名:位置}
変数に設定されている文字列の「位置」の位置から「長さ」文字の長さの文字列を取り出します。 位置は0からカウントし、「長さ」が省略された場合は「位置」の位置から最後までの文字列を取り出します。また、「変数名」が@の場合は「位置」は位置パラメータに、「長さ」は個数になります。
$ echo $HOME
/home/merry ← 環境変数HOMEの値です
$ echo ${HOME:6}
merry
$ echo ${HOME:6:2}
me
$
$ set PARA1 PARA2 PARA3 PARA4 ← 位置パラメータ1から4へ値を設定します
$ echo $1 $2 $3 $4 ← 位置パラメータの値を確認します
PARA1 PARA2 PARA3 PARA4
$ echo ${@:3:1} ← 位置パラメータ3を指定します
PARA3
$

パターンマッチング

【表6-7】パターンマッチング演算子一覧
形式説明/例題
${変数名#パターン} 変数の値の最初の部分と「パターン」が一致した場合、最も短く一致する部分を削除し、残りの部分を返します。
$ echo $PWD ← 環境変数PWD(カレントディレクトリの絶対パス名)の値を表示します
/home/merry/mybin
$ rtn=${PWD#/*/} ← "/"で始まり"/"で終るパターンを指定します
$ echo $rtn
merry/mybin ← 先頭の"/home/"とパターンが一致しました
$
${変数名##パターン} 変数の値の最初の部分と「パターン」が一致した場合、最も長く一致する部分を削除し、残りの部分を返します。
$ echo $PWD
/home/merry/mybin
$ rtn=${PWD##/*/}
$ echo $rtn
mybin ← 先頭の"/home/merry/"とパターンが一致しました
$
${変数名%パターン} 変数の値の最後の部分と「パターン」が一致した場合、最も短く一致する部分を削除し、残りの部分を返します。
$ echo $HOSTNAME
merry.org.jp
$ echo ${HOSTNAME%.*}
merry.org ← 最後の".jp" とパターンが一致しました
$
${変数名%%パターン} 変数の値の最後の部分と「パターン」が一致した場合、最も長く一致する部分を削除し、残りの部分を返します。
$ echo $HOSTNAME
merry.org.jp
$ echo ${HOSTNAME%%.*}
merry ← 最後の".org.jp" とパターンが一致しました
$

文字列長の取得

【表6-8】文字列長の取得演算子一覧
形式説明/例題
${#変数名}変数に設定されている文字列の文字数を返します。
$ echo $HOSTNAME
merry.org.jp
$ echo ${#HOSTNAME}
12 ← "merry.org.jp"の文字数です
$

文字列の連結

変数の値と文字列の連結を行うための演算子はありませんので、変数名に$を付けて参照して、その後に文字列を指定すれば連結します。ただし、シェルにとって変数名が明確になるように指定しないと連結出来ません。連結出来ない場合は、変数を${変数名}の形式で参照するとよいでしょう。

$ var1="Hello_" ← 変数var1に「Hello_」を設定します
$
$ echo $var1World ← 変数var1に「World」を連結しようとしました
 ← シェルはvar1Worldという変数の値を表示しようとしましたが、var1Worldは未定義のため何も表示しません
$ echo $var1 World ←echoコマンドの引数として、変数var1と文字列を指定(文字列の連結ではない)します
Hello_ World
$
$ echo ${var1}World ← ${変数名}の形式でvar1の値を参照することで、変数var1を明確にします
Hello_World
$
$ myll="ls -l"
$ $myll TMP ← 「ls -l TMP」を実行します
合計 176152
drwxr-xr-x 4 merry merry      4096 2010-08-22 09:58 DOWNLOAD
drwxr-xr-x 3 merry merry      4096 2010-08-19 16:05 PHOTO
drwxr-xr-x 2 merry merry      4096 2010-08-25 16:37 WORK
-rw-r--r-- 1 merry merry        38 2010-08-26 10:42 memo.txt
$

日本語文字列と連結する場合は変数名は明確になることが多いのですが、できるだけ${変数名}の形式で指定しておいた方がよいでしょう。

$ var2=今日は
$
$ echo $var2世界
今日は世界
$ echo ${var2}世界 ← こちらの形式を推奨します
今日は世界
$