私は現在、パラメータ拡張、特にパターンマッチングを通じてパラメータ値の一部を削除できるさまざまな形式を理解しようとしています。この問題を解決するには、まず拡張に焦点を当てます${parameter#word}
。
マニュアルの2つの関連セクション(man bash
)(強調):
${parameter#word}
${parameter##word}
一致するプレフィックスパターンを削除します。これ単語が拡張され、次のようなパターンが生成されます。パス名拡張、以下のパターン一致で説明されている規則を使用して、パラメータの拡張値を一致させます。パターンがパラメータ値の先頭に一致する場合、拡張結果は、最短一致パターン(case'#'
)または最長一致パターン('##'
case)が削除されたパラメータの拡張値です。 [...]
パス名拡張
単語分割後のbashは、-fオプションが設定されていない限り、各単語で*、?と[文字を検索します。これらの文字のいずれかが発生すると、その単語はパターンとして扱われ、パターンと一致するファイル名のアルファベット順のリストに置き換えられます(下記のパターン一致を参照)。 [...]
ただし、端末セッションの次の部分を考慮してください。
root@cerberus ~/scripts # mkdir test
root@cerberus ~/scripts # cd test
root@cerberus ~/scripts/test # touch foo
root@cerberus ~/scripts/test # String=foobar
root@cerberus ~/scripts/test # printf '%s\n' ${String#foo}
bar
root@cerberus ~/scripts/test # printf '%s\n' ${String#*}
foobar
root@cerberus ~/scripts/test #
最後のコマンド以降の出力は理解できません。マニュアルによると、少なくとも現在のディレクトリにある唯一のファイルであるため、*
拡張する必要があります。これが「パス名拡張がパターンを生成するのと同じ」という私の概念です。foo
foo
したがって、この場合は次のprintf '%s\n' ${String#*}
出力を提供する必要があります。printf '%s\n' ${String#foo}
明らかにこれは本当ではありません。私の理解はどこで間違っていますか?
ベストアンサー1
~についてパターンマッチング:
*
空の文字列を含むすべての文字列と一致します。
そして、部分文字列を削除するためのパラメータ拡張では、最短#
一致を実行し、##
最長一致を実行します。
これは最初から空の文字列を削除することです(最短一致)。
$ printf '%s\n' "${String#*}"
foobar
これにより、foobar
最初から削除されます(最も長い一致)。
$ printf '%s\n' "${String##*}"
$
説明の最後の段落について:パラメータ拡張を使用すると、現在のディレクトリのファイルに関係なくサブストリングが削除されます。このパターンはファイルではなくパラメータ値と一致し、それをパラメータ値のテキスト処理操作として扱います。