ネストされたパラメータ拡張を参照する正しい方法は何ですか?

ネストされたパラメータ拡張を参照する正しい方法は何ですか?

入れ子になったパラメータ拡張を処理するときに、次のいずれかを参照する正しい方法は何ですか?

これ:

var="${var#"${var%%[![:space:]]*}"}"

またはこれ:

var="${var#${var%%[![:space:]]*}}"

私はそれが2つの方法で行われるのを見ました。最初のバリエーションはスタックオーバーフロー回答。これは、この質問に対する最も高い支持を得た答えの1つです(質問は変数で空白を切り取る方法です)。


また、リテラルテキストの「単語」や「パターン」ではなく変数を使用するときに物事を参照する方法を扱う評判の良いソースを見つけるのに苦労しています。次の2つの項目のうち、正しいものは何ですか?

これ:

strip_ext="${filename%."$filename_ext"}"

またはこれ:

strip_ext="${filename%.$filename_ext}"

答え1

展開の右辺をどのように解釈したいかによって異なります。パターンまたはリテラル文字列として。

ここで引用されていない*パターンは文字列全体を食べます。引用符は文字通りアスタリスクを削除しました。

var='foo*'
echo ":${var%%*}:"                 # this prints ::
echo ":${var%%"*"}:"               # this prints :foo:

パターンを変数に入れると、効果は同じです。

var='foo*'
pat='*'
echo ":${var%%$pat}:"              # this prints ::
echo ":${var%%"$pat"}:"            # this prints :foo:

または右側の別のパラメータに展開します。

var='foo*'
pat='x*x'
echo ":${var%%${pat//x}}:"         # this prints ::
echo ":${var%%"${pat//x}"}:"       # this prints :foo:

${pat//x}結果は*今回も同様です。)

私が試したすべてのPOSIX様シェル(Bash、ksh、yash)は同じ動作をします。もちろん、Zshは異なり、右側のパラメータ拡張はすべて単語分割問題と同様にZshで参照されます。拡張機能でこれを変更するために使用できる演算子があると思います。

答え2

どちらの場合も、一般的に最初の方法が欲しいものです。右の文字列を${var#*a}引用符で囲まないと、パターンとして解釈/拡張されます。この例では、先頭のテキストは最初の文字まで削除されますa。引用した場合:${var#"*a"}拡張機能はテキストを削除します*a。次のような場合は問題になる可能性があります。

"${filename%."$filename_ext"}"

"$filename_ext"パターン文字を含めることができます。同様に$var、inに"${var#"${var%%[![:space:]]*}"}"パターン文字(*?[)を含めることができ、それをパターンとして解釈したくない場合は、次のように拡張子を引用してください。

"${var#"${var%%[![:space:]]*}"}"

変数の割り当ての右側の部分は引用されていると見なされ、引用は必要ありません(ただし破損しません)。両者にも当てはまる。

      var=${var#"${var%%[![:space:]]*}"}
strip_ext=${filename%."$filename_ext"}

関連情報