Integer Variables
基本的に、Shell Script では、変数は文字だが、Integer として使う方法がある。
declare -i variable
を指定すると、その変数をIntegerにすることができる。ちなみに、文字を代入してもエラーは起こらないが、0という扱いになる。
調べてみると、declare
はtypeset
のシノニムで、変数のプロパティを変更するもの。次のものがある。
-
-r
Readonly -
-i
Integer -
-a
array -
-f
function -
-x
export
$ p="3+2"
$ echo $p
3+2
$ declare -i p
$ p="3+2"
$ echo $p
5
$ p="abc"
$ echo $p
0
Arithmetic Expression
C言語のような構文が使える。
いくつかの方法がある。
let
let n=100/4
(( .. ))
let と同じだが、著者は、let の方が好みらしい。スペースが使えるとか(よくわかってない)
((++x))
((p=x/100))
(( p= $(ls | wc -l) * 10)) # 空白あってもなくても同じだった。
上記のスペースのいちが曖昧。あとで確認
$(( .. ))
これは、Substitution なので、計算結果が置き換えられる。
p=$(( x / 100 ))
integer で定義された変数を使う
declare -i で定義された変数を使う
num="30 % 8"
サンプル
declare -i x
$ x=100/2
$ echo $x
50
$ $((++x)) # Substitution なので、51に置き換えられて解釈される
-bash: 51: command not found
$ ((++x))
$ echo $x
52
$ x=$((x+1))
$ echo $x
53
$ (( p= $(ls | wc -l) * 10)) # スペースを詰めても同じ結果だった。
$ echo $p
230
Tips
-
クオートは必要ない。あってもいいけど
-
((..))はif, while で使えるけど、0がfalseになるので注意(コマンド実行と逆)
-
0始まりの数字は、8進数として計算される
-
For ループの ((..; ..; ..)) 自体は Arithmetic Expression ではないが、内部は Arithmetic Expression
サンプル
サンプルが面白かったので写経。ポイントとしては、Integer Variable と$((..))
((..))
構文で計算しているところ。ちなみに、$RANDOM
はIntegerの範囲のランダムな数値を返すので、若干偏りがあるような気がするが、余りを求めることで、特定の範囲のランダムな数字を取得している。
# !/bin/bash
# Get a random number 0 < target < 100
declare -ir target=$(( ($RANDOM % 100)))
declare -i guess=0
until (( guess == target )); do
read -p "Guess the number: " guess
# guess should not be 0
(( guess )) || continue # 渋い
if (( guess < target )); then
echo "Greater than that!"
elif (( guess > target )); then
echo "Less than that!"
else
echo "You've found it!"
fi
done
exit 0
実行
$ ./game
Guess the number: 50
Greater than that!
Guess the number: 75
Less than that!
Guess the number: 62
Greater than that!
Guess the number: 68
Less than that!
Guess the number: 66
Less than that!
Guess the number: 65
Less than that!
Guess the number: 64
export variables
サブプロセスに変数を使えるようにする。呼び元には、残念ながら変数を渡せない。(この書き方では)
export var="value"
declare -x var="value"
さらに、サブプロセスには、アトリビュートは渡らない。アトリビュートは、例えば、declare -xr
のxrなど。
サンプル
ポイントとしては、親で定義して、export
もしくは、declare -x
で定義したものはサブプロセスでも使えるが、そのアトリビュートは渡らないので、親でreadOnly指定をしても子で上書きできる。子で、export しても、親の方にはその変数は渡らない。ちなみに、サブプロセスからペアレントに環境変数を渡したかったらファイル経由で行くしかないとのこと。PowerShell
はスコープがあるから可能だった。
parent
# !/bin/bash
declare -xr parentVariable="Parent worte this"
declare -r parentOnlyVariable="Parent only variable"
echo "Parent: ParentVariable: ${parentVariable}"
echo "Parent: ParentOnlyVariable: ${parentOnlyVariable}"
./child
echo "Parent: ParentVariable: ${parentVariable}"
echo "Parent: ParentOnlyVariable: ${parentOnlyVariable}"
echo "Parent: ChildVariable: ${childVariable}"
child
# !/bin/bash
echo "Child: ParentVariable: ${parentVariable}"
echo "Child: ParentOnlyVariable: ${parentOnlyVariable}"
declare -x childVariable="Child only variable"
parentVariable="override by child"
echo "Child: ParentVariable: ${parentVariable}"
echo "Child: ParentOnlyVariable: ${parentOnlyVariable}"
echo "Child : ChildVariable: ${childVariable}"
実行
$ ./parent
Parent: ParentVariable: Parent worte this
Parent: ParentOnlyVariable: Parent only variable
Child: ParentVariable: Parent worte this
Child: ParentOnlyVariable:
Child: ParentVariable: override by child
Child: ParentOnlyVariable:
Child : ChildVariable: Child only variable
Parent: ParentVariable: Parent worte this
Parent: ParentOnlyVariable: Parent only variable
Parent: ChildVariable:
Array
- x[0]="some"
- x[1]="word"
- ${x[0]} # return some
- ${x[1]} # return word
${x[@]} や ${x[*]}
は全ての値を取得する。(クオートは、$*
や$@
と同じように動く
定義
declare -a var
もしくは、上記のようにindex付きの変数にアサインする。
ar=(1 2 3 a b c)
と行った記述も可能。
カウント
- ${#array[@]} # 要素数を返す
- ${!array[@]} # インデックスのみを返す
Array は export 出来ないらしい。bash 4 は、アソシエーティブArray を使えるらしい。index ではなく、名前を指定できる。(Map?) declare -A array
で良いらしい。
$ ar=(hello people this is array)
$ declare -p ar
declare -a ar='([0]="hello" [1]="people" [2]="this" [3]="is" [4]="array")'
$ echo ${ar[3]}
is
$ ar[12]="again"
$ declare -p ar
declare -a ar='([0]="hello" [1]="people" [2]="this" [3]="is" [4]="array" [12]="again")'
$ echo ${$ar[@]}
-bash: ${$ar[@]}: bad substitution
$ echo ${#ar[@]}
6
$ echo ${!ar[@]}
0 1 2 3 4 12
ちなみに、-p
は全ての変数の値を表示するためのオプション.