Bash パラメータ拡張

Bash パラメータ拡張

Bash(私の場合は4+)は、文字列で利用可能なすべての引数拡張関数が配列で利用可能であることを読み書きしました。今日は配列ポップと同様の機能を設定しようとしました。次の構文に似たものを使用しました。

declare -a arr=( 0 1 2 3 4 5 )
arr=( ${arr[@]:0:(-1)} )

驚いたことに、Bashは次のように文句を言った。

-bash: (-1): substring expression < 0

文字列を使用してこれを実行すると、構文は期待どおりに機能します。たとえば、

var="see spot run"
var="${var:0:(-1)}"
echo "$var"
  see spot ru

私は配列に対してこれを行うことができることを知っています(そしてそれがうまくいくかどうかテストしました):

declare -a arr=( 0 1 2 3 4 5 )
arr=( ${arr[@]:0:((${#arr[@]}-1))} )
echo ${arr[@]}
    0 1 2 3 4

問題は、すべての文字列引数拡張が配列で機能する場合(-1)構文が期待どおりに機能しないのはなぜですか?私はここで単純なものを見落としているのでしょうか、それとももっと深いものがありますか?

ベストアンサー1

この質問に対する答えは、すべての文字列パラメータ拡張が配列で機能するわけではないようです。コメントを見て、Bashリファレンスマニュアル(don_crisstiによって提供されたリンク、ありがとう)を読んだ後、部分文字列拡張の負のインデックス付けに関する警告が表示されます。 Bashのマニュアルに記載されているように(シェルパラメータ拡張):

${parameter:offset:length}

これを部分文字列拡張と呼びます。それは拡張される長さ指定された文字から始まるパラメータ値の文字オフセット。引数が@インデックス配列または関連配列名の場合、以下の説明のように結果が異なります。@*

...

@引数が添字または添字付きのインデックス配列名の場合、*結果は次のようになります。長さで始まる配列メンバーです${parameter[offset]}。負の数オフセット指定された配列の最大インデックスより1大きい値に基づいています。次の場合、拡張エラーが発生します。長さ0より小さい数字として評価されます。

don_crisstiが指摘したように、ここで実行される長さの評価は、参照文字列/サブ文字列の長さではなく、長さ属性の割り当て中に実行される評価です。 don_crisstiの例は次のとおりです。

a=2
printf %s\\n "${arr[@]:3:(a+1)}"

長さ割り当て(a + 1)の算術評価部分が負の値を生成する場合、または私の場合など、値自体が静的に負の数に渡される場合、これは拡張エラーです。つまり、次の両方の状況で拡張エラーが発生する可能性があります。

declare -a arr=( 0 1 2 3 4 5 )
# length evaluates to (-1)
a=2
printf %s\\n "${arr[@]:3:(a-3)}"
  -bash: (a-3): substring expression < 0

# or length is assigned as (-1)
arr=( ${arr[@]:0:(-1)} )
  -bash: (-1): substring expression < 0

Bashのマニュアルによると、これは両方のケースで予想される動作です。

おすすめ記事