bash,dash,zshにおける演算と外部コマンドの出力について
ここではbash,dash,zshのシェルにおいて演算結果と外部コマンドの出力の展開についてを扱う。どちらもその記述を行った部分について「展開」されるだけなので、それをそのまま(出力の全体もしくは一部として)表示してもシェル上の変数に代入してもよい。
演算
2つの丸括弧で計算式をくくって先頭に「$」を付けるとその計算の結果に展開される。
$ echo 123たす234は$((123+234)) 123たす234は357
もちろん、0で割ろうとするとエラーとなる。メッセージの出かたはそれぞれのシェルで微妙に異なる。
bash$ echo $((2/0)) bash: 2/0: division by 0 (error token is "0") dash$ echo $((2/0)) dash: arithmetic expression: division by zero: "2/0" zsh$ echo $((2/0)) zsh: division by zero
分母が0でない割り算でも、zsh以外はうまく処理できないことがある。
$((1/5))
はいずれも「0」に展開されるが、zshでは小数点を付けると計算される。しかし、bash,dashではエラーになる。
bash$ echo $((1.0/5.0)) bash: 1.0/5.0: syntax error: invalid arithmetic operator (error token is ".0/5.0") dash$ echo $((1.0/5.0)) dash: arith: syntax error: "1.0/5.0" zsh$ echo $((1.0/5.0)) 0.20000000000000001
外部コマンドの出力
1つの丸括弧でコマンド行をくくって先頭に「$」を付けるとそのコマンドの出力に展開される。これは入れ子にすることもできる。下は入れ子の例で、相対パスで渡されたファイルやディレクトリの場所を絶対パスに変換している。
$ INFILE=[ファイルやディレクトリの相対パスもしくは絶対パス] $ INFILE=$(cd $(dirname ${INFILE}) && pwd)/$(basename ${INFILE}) $ echo ${INFILE} [絶対パスが表示される] $ unset INFILE
具体的な例として、ディレクトリ/tmp/work/にいるとして同ディレクトリのtest.txtを示す相対パス「./test.txt」がINFILEだとすると
[/tmp/work]$ INFILE=./test.txt [/tmp/work]$ INFILE=$(cd $(dirname ${INFILE}) && pwd)/$(basename ${INFILE}) [/tmp/work]$ echo ${INFILE} /tmp/work/test.txt [/tmp/work]$ unset INFILE
このように絶対パスになっている。
外部コマンドの出力を扱う書き方として、バッククォート文字(`)2つで囲む書き方もあるが、入れ子にはできない。
(2009/11/16)バックスラッシュで内側のバッククォートをエスケープすると入れ子にすること自体は可能(bash,dash,zshで確認・id:Magicant氏に感謝)だが非推奨。また、(本記事とは関係ないが)tcshではエラーの原因となる。
$ for i in `seq 5`; do echo ${i}; done; unset i 1 2 3 4 5
上の例は
for i in $(seq 5); do echo ${i}; done; unset i
とも書ける。
いずれの形式においても、外部コマンドの出力はパイプで別のプロセスに渡された結果でもよい。
$ echo "HDD:$(nc 127.0.0.1 7634 | awk -F\| '{printf $4}')" HDD:[温度の値]
関連記事:
使用したバージョン: