light log

学んだこととか

シェル変数やりなおし

入門UNIXシェルプログラミング―シェルの基礎から学ぶUNIXの世界

入門UNIXシェルプログラミング―シェルの基礎から学ぶUNIXの世界

昨日に引き続き、積ん読してた『入門UNIXシェルプログラミング』を読んだのでメモ。

今日はシェル変数。

基本から。

=の前後にスペースを入れてはいけない

最初のころやりがち。

$ FOO=foo
$ FOO = foo # NG
-bash: FOO: command not found

変数名の大文字と小文字は区別される

$FOO$Fooは別の変数として扱われる。変数名はすべて大文字とするのが慣例。

$ FOO=upper
$ Foo=lower
$ echo $FOO $Foo
upper lower

変数名に使用できる文字は英数字とアンダースコア

ただし、先頭に数字は不可。

$ BAR_012=bar
$ 012_BAR=bar # NG
-bash: 012_BAR=bar: command not found
$ _012BAR=bar # OK

$で変数の値を参照する

変数名として使える文字を後ろに続けるときは波括弧が必須。

$ FOO=foo
$ echo $FOO
foo
$ echo $FOOBAR    # $FOOBAR という変数として解釈される

$ echo ${FOO}BAR  # 波括弧をつけるとOK
fooBAR
$ echo ${FOO}/BAR # この場合どっちでもいい
foo/BAR
$ echo $FOO/BAR
foo/BAR

クォートの中の変数

ダブルクォートは変数展開する。シングルクォートはしない。

$ echo "$FOO"
foo
$ echo '$FOO'
$FOO

変数の初期設定(=)

こんなの初めて知った。

${VAR:=value}とすると、$VARが未定義の場合または定義済みで値がヌルの場合のみvalueを設定する。

${VAR=value}のようにコロンを省略すると、$VALUEが未定義の場合のみvalueを設定する。

NULL=
HAS_VALUE="initial value"

echo ${UNDEFINED:="new value"}
echo $UNDEFINED
echo ${NULL:="new value"}
echo $NULL
echo ${HAS_VALUE:="new value"}
echo $HAS_VALUE

echo ============================

unset UNDEFINED
NULL=
HAS_VALUE="initial value"

echo ${UNDEFINED="new value"}
echo $UNDEFINED
echo ${NULL="new value"}
echo $NULL
echo ${HAS_VALUE="new value"}
echo $HAS_VALUE

# => new value
# => new value
# => new value
# => new value
# => initial value
# => initial value
# => ============================
# => new value
# => new value
# => 
# => 
# => initial value
# => initial value

変数の初期設定(-)

変数が未定義やヌルの場合に、指定した値を返すが、変数の値は書き換えない。コロンの有無による差異は=と同じ。

NULL=
HAS_VALUE="initial value"

echo ${UNDEFINED:-"new value"}
echo $UNDEFINED
echo ${NULL:-"new value"}
echo $NULL
echo ${HAS_VALUE:-"new value"}
echo $HAS_VALUE

echo ============================

unset UNDEFINED
NULL=
HAS_VALUE="initial value"

echo ${UNDEFINED-"new value"}
echo $UNDEFINED
echo ${NULL-"new value"}
echo $NULL
echo ${HAS_VALUE-"new value"}
echo $HAS_VALUE

# => new value
# => 
# => new value
# => 
# => initial value
# => initial value
# => ============================
# => new value
# => 
# => 
# => 
# => initial value
# => initial value

変数の初期設定(?)

変数が未定義やヌルの場合に、指定したメッセージを表示してシェルスクリプトの処理を終了する。メッセージを省略するとデフォルトの値が使われる。

$ NULL=
$ echo ${NULL:?"NULL is null"}
-bash: NULL: NULL is null
$ echo ${NULL?"NULL is null"}

$ echo ${NULL:?}
-bash: NULL: parameter null or not set

変数の初期設定(+)

-の逆で、変数が未定義やヌル 以外の 場合に、指定した値を返すが、変数の値は書き換えない。

NULL=
HAS_VALUE="initial value"

echo ${UNDEFINED:+"new value"}
echo $UNDEFINED
echo ${NULL:+"new value"}
echo $NULL
echo ${HAS_VALUE:+"new value"}
echo $HAS_VALUE

echo ============================

unset UNDEFINED
NULL=
HAS_VALUE="initial value"

echo ${UNDEFINED+"new value"}
echo $UNDEFINED
echo ${NULL+"new value"}
echo $NULL
echo ${HAS_VALUE+"new value"}
echo $HAS_VALUE

# => 
# => 
# => 
# => 
# => new value
# => initial value
# => ============================
# => 
# => 
# => new value
# => 
# => new value
# => initial value

引数まわり

  • $0: コマンド自身
  • $1$9: 1番目〜9番目の引数(位置パラメタ)
  • $#: 引数の数
  • $*: 引数全体
  • $@: 引数全体

$*$@の違いは、ダブルクォートで囲んで展開した場合に、引数全体を一つのダブルクォートで囲むか、個々をダブルクォートで囲むか。

10番目以降の引数を参照したければ、shiftを使う。

echo $0 $1 $2 $3 $4 $5 $6 $7 $8 $9

echo $#
echo $@
echo $*

shift
echo $0 $1 $2 $3 $4 $5 $6 $7 $8 $9

shift 2
echo $0 $1 $2 $3 $4 $5 $6 $7 $8 $9

# $ sh foo.sh a b c d e f g h i j k l m n
# => foo.sh a b c d e f g h i
# => 14
# => a b c d e f g h i j k l m n
# => a b c d e f g h i j k l m n
# => foo.sh b c d e f g h i j
# => foo.sh d e f g h i j k l

$?

コマンドの終了ステータス。

$ mkdir
usage: mkdir [-pv] [-m mode] directory ...
$ echo $?
64
$ mkdir foo
$ echo $?
0

$$

現在のコマンドのプロセスID。

$!

バックグラウンドで実行しているコマンドのプロセスID。

$ sleep 10 &
[1] 65079
$ echo $!
65079
$ wait $!
[1]+  Done                    sleep 10

$-

シェル起動時のフラグ。

最後に

「変数の初期設定」のところは可読性悪いし、if文使った方がいいよねって本にも書いてある。