Edited at

bash Tips - コマンド置換と算術式展開、パラメータ展開

More than 3 years have passed since last update.


bash Tips - コマンド置換と算術式展開、パラメータ展開


コマンド置換 - `command`ではなく$(command)を使う


  • なぜか?ネストできるから


バッククォートはネストできない

# echo `echo "0123456789abcdefg" | cut -b `echo "11"``

cut: option requires an argument -- 'b'
詳しくは `cut --help' を実行して下さい.
echo 11


ダラーと丸括弧ならネストできる

# echo $(echo "0123456789abcdefg" | cut -b $(echo "11"))

a


コマンド置換

  コマンド置換 (command substitution) を用いると、コマンド名をコマンドの出力で置き換えできます。

  コマンド置換には以下の 2 つの形式があります:

    \$(command)

  または

    `command`

  bash による展開は、command の実行およびコマンド置換の部分をコマンドの標準出力と

  置換することにより実行されます。

  この際、末尾の改行文字は削除されます。

  文字列の途中にある改行文字は削除されませんが、単語分割の際に削除されることがあります。

  コマンド置換 \$(cat file) は、同じ意味を持ち、しかも高速な \$(< file) に置き換え可能です。

  バッククォートを使う古い形式の置換を用いたとき、

  バックスラッシュは文字通りの意味を保ちますが、\$、 '、 \、の前にある場合は例外となります。

  バックスラッシュが前置されていないバッククォートがあると、そこでコマンド置換は閉じられます。

  \$(command) という形式を用いたときは、括弧の間にある全ての文字がコマンドとなります。

  特別扱いされる文字はありません。

  コマンド置換は入れ子にできます。

  バッククォート形式の時に入れ子を行うには、

  内側のバッククォートをバックスラッシュでエスケープします。

  置換がダブルクォート内部にある場合には、

  置換の結果に対する単語分割とパス名展開は行われません。

                                       man bash より引用



算術式展開 - expr $m + $nではなく$((m+n))を使う


  • なぜか?bash組み込みであり、インクリメントできるから


exprはインクリメントできない

# i=1; i=$( expr ++$i ); echo "$i"

++1


ダラーと丸括弧2重ならインクリメントできる

# i=1; i=$((++i)); echo "$i"

2


算術式展開

  算術式展開を使うと、算術式を評価して、その結果に置換できます。

  算術式展開のフォーマットを次に示します:

    \$((expression))

  expression はダブルクォート内部にある場合と同様に扱われますが、

  括弧の内側のダブルクォートが特別扱いされることはありません。

  式に含まれる全てのトークンに対して、

  パラメータ展開・文字列展開・コマンド置換・クォートの削除が行われます。

  算術式置換は入れ子にできます。

  評価は後述の 算術式評価で示す規則に基づいて行われます。

  expression が不正であれば、 bash は評価の失敗を示すメッセージを出力し、置換を全く行いません。

                                       man bash より引用



パラメータ展開


${parameter:-word}

デフォルトの値を使います。 parameter が設定されていないか空文字列であれば、 word を展開したものに置換されます。そうでなければ、 parameter の値に置換されます。

${parameter:=word}

デフォルトの値を代入します。 parameter が設定されていないか空文字列であれば、 word を展開したものが parameter に代入されます。それから parameter の値への置換が行われます。 位置パラメータや特殊パラメータへの代入をこのように行うことはできません。

${parameter:?word}

空文字列または設定されていない場合にエラーを表示します。 parameter が空文字列または設定されていない場合、word を展開したもの (word がなければ パラメータが空文字列または設定されていないことを示すメッセージ) が標準エラー出力に出力されます。シェルが対話的でなければ、 シェルは終了します。パラメータに空文字列以外が設定されていれば、 parameter の値への置換が行われます。

${parameter:+word}

別の値を使用します。 parameter が空文字列または設定されていなければ、空文字列に置換されます。 そうでなければ word を展開したものに置換されます。

\${parameter:offset:length}

部分文字列展開。 parameter を展開したものから最大 length 文字を取り出します。 先頭の文字は offset で指定します。length を省略すると、 offset で指定した文字を先頭にして、 parameter の残り全部が含まれる部分文字列に展開します。 length と offset は算術式です (後述の 算術式評価 を参照)。 offset を評価すると 0 未満の数になる場合、この値は parameter の値の末尾からのオフセットとして使われます。 length を評価すると 0 未満の数になる場合、 parameter が @ ではなく、配列でも連想配列でもなければ、 この値は文字数ではなく parameter の値の末尾からのオフセットとして使われ、 展開結果は 2 つのオフセットの間の部分文字列となります。 parameter が @ ならば、結果は offset から始まる length 個の位置パラメータになります。 parameter が @ または * のインデックスが付いている配列名ならば、 結果は配列の \${parameter[offset]} を先頭とする要素 length 個となります。 負の offset は、指定された配列の最大のインデックス + 1 からの相対値と解釈されます。 連想配列に部分文字列展開した場合の結果は決められていません。 負のオフセットを指定するときには、:- 式と混同されないよう、 1 つ以上の空白でコロンと離す必要があることに注意してください。 位置パラメータを使う場合以外は、 部分文字列のインデックスは 0 から始まります。位置パラメータの場合には、 インデックスは 1 から始まります。 位置パラメータが使われて offset が 0 の場合、 $0 の値が先頭に置かれます。

\${!prefix*}

\${!prefix@}

前方一致する変数名。 prefix で始まる全ての変数の名前に展開して、 IFS 特殊変数の最初の文字によって区切ります。 ダブルクォートの中で @ が使われた場合、それぞれの変数の名前は 別々の単語に展開されます。

\${!name[@]}

\${!name[*]}

配列のキーのリスト。 name が配列変数であれば、配列 name の インデックス (キー) のリストに展開されます。 name が配列でない場合は、name が設定されていれば 0 に、 そうでなければ空に展開されます。 ダブルクォートの中で @ が使われた場合、それぞれのキーは 別々の単語に展開されます。

\${#parameter}

パラメータの長さ。 parameter の値に含まれる文字数に置換されます。 parameter が * または @ ならば、位置パラメータの数に置換されます。 parameter が * または @ が添字になっている配列名ならば、配列中の要素数に置換されます。

\${parameter#word}

\${parameter##word}

パターンに前方一致した部分を取り除く。 word が展開され、パス名展開の場合と同じようなパターンを作ります。 このパターンが parameter の値の先頭部分とマッチする場合、展開して得られる値は parameter を展開した値から最短一致パターン (#''の場合) または最長一致パターン (##'' の場合) を取り除いたものになります。 parameter が @ または * である場合、 パターンを削除する操作は全ての位置パラメータに順番に適用され、 展開結果はリストとして得られます。 parameter が @ または * が添字になっている配列変数である場合、 パターンを削除する操作は配列の全ての要素に順番に適用され、 展開結果はリストとして得られます。

\${parameter%word}

\${parameter%%word}

パターンに後方一致した部分を取り除く。 word が展開され、パス名展開の場合と同じようなパターンを作ります。 このパターンが parameter を展開した値の末尾の部分とマッチする場合、展開結果は parameter を展開した値から最短一致パターン (%'' の場合) または最長一致パターン (%%'' の場合) を取り除いたものになります。 parameter が @ または * である場合、 パターンを削除する操作は全ての位置パラメータに順番に適用され、 展開結果はリストとして得られます。 parameter が @ または * が添字になっている配列変数である場合、 パターンを削除する操作は配列の全ての要素に順番に適用され、 展開結果はリストとして得られます。

\${parameter/pattern/string}

パターンの置換。 pattern が展開され、 パス名展開の場合と同じようなパターンを作ります。 parameter の展開が行われ、 その値のうち pattern に最長一致する部分が string に置換されます。 pattern が / で始まる場合には、pattern に マッチした部分は全て string に置換されます。 そうでない場合には、最初にマッチした部分だけが置換されます。 pattern が # で始まる場合には、パターンは parameter を展開した値の先頭にマッチしなければなりません。 pattern が % で始まる場合には、パターンは parameter を展開した値の末尾にマッチしなければなりません。 string が空の場合には pattern にマッチした部分は削除されます。 またこの場合には、pattern の後に続く / は省略可能です。 parameter が @ または * である場合、置換操作は全ての位置パラメータに順番に適用され、 展開結果はリストとして得られます。 parameter が @ または * が添字になっている配列変数である場合、 置換操作は配列の全ての要素に順番に適用され、 展開結果はリストとして得られます。

\${parameter^pattern}

\${parameter^^pattern}

\${parameter,pattern}

\${parameter,,pattern}

大文字小文字の変換。 parameter に含まれるアルファベットの大文字小文字を変換します。 pattern が展開され、 パス名展開の場合と同じようなパターンを作ります。 ^ 演算子は pattern にマッチした小文字を大文字に変換します。 , 演算子は pattern にマッチした大文字を小文字に変換します。 ^^ 演算子と ,, 演算子は、マッチした全ての文字を変換します。 ^ 演算子と , 演算子の場合は、マッチした最初の文字だけ変換します。 pattern を省略した場合、? を指定したものとして扱われ、 全ての文字にマッチします。 parameter が @ または * である場合、大文字小文字の変換は全ての位置パラメータに順番に適用され、 展開結果はリストとして得られます。 parameter が添字に @ または * の付いた配列変数の場合は、配列の要素のそれぞれに大文字小文字の変換が適用され、 結果はリストに展開されます。

                                       man bash より引用