「シェルスクリプトの基礎 - 変数」の版間の差分

提供:MochiuWiki - SUSE, Electronic Circuit, PCB
ナビゲーションに移動 検索に移動
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.



コマンドの実行結果を変数に代入する

lsgrepfind等のコマンドの実行結果を変数に代入するには、以下のように記述する。

変数=$(コマンド)
   または
変数=`コマンド`


以下の例では、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