bash - extglob 2番目の「0個以上」演算子が機能しません。

bash - extglob 2番目の「0個以上」演算子が機能しません。

一方:

$ shopt -s extglob
$ TEST="    z abcdefg";echo ">>${TEST#*( )z*( )}<<"
>> abcdefg<<

文字「a」の前にスペースがあるのはなぜですか?二度目も*( )空間にふさわしくしたかったのですが、そうするには適していませんね。

私は次の結果を期待しています:

$ echo ">>$(echo -n "${TEST}" | perl -pe "s/^ *z *//g")<<"
>>abcdefg<<

*( )次の文字(「a」など)を指定すると、2番目の文字が一致します。

$ shopt -s extglob
$ TEST="    z abcdefg";echo ">>${TEST#*( )z*( )a}<<"
>>bcdefg<<

ヒットバージョン: GNU bash, version 4.3.48(1)-release (x86_64-pc-linux-gnu)

答え1

${TEST#...}最も短い文字列、zの後にスペースがない文字列と一致します。あなたは${TEST##...}最長のマッチが欲しいです。

答え2

これは、貪欲ではない部分文字列の削除と使用中のパターンの種類との相互作用が原因で発生します。

~からバッシュマニュアル

?(pattern-list)

指定されたパターンが0個または1個一致します。

*(pattern-list)

指定されたパターンのゼロ以上の発生と一致します。

+(pattern-list)

与えられたパターンと1つ以上一致します。

私が好きなbashの説明から文字列演算

${string#substring}

$substring以前に最も短い一致を削除します$string

${string##substring}

$substring最も長い前の一致を削除します$string

したがって、 を指定するときは、次のように${TEST#*( )z*( )}言うことです。 「ゼロ個以上のスペースがある最短の部分文字列aを削除し、zその後にゼロ個以上のスペースが続きます。

最後の空白がある一致はない項目よりも長いため、最後の空白は一致しません。

この問題を解決するには、${TEST##*( )z*( )}ゼロを超えるスペースで終わる最長のプレフィックス一致を使用するか、${TEST#*( )z+( )}1つ以上のスペースで終わる最短のプレフィックス一致を使用できます(1つのスペースで終わる最短のプレフィックス一致と機能的に同じです)。

答え3

is(perl)正規表現を模倣するには、regexnot aを使用しますpattern

$ test="    z abcdefg"
$ regex='^ *z *(.*)'
$ [[ $test =~ $regex ]]
$ echo ">>${BASH_REMATCH[1]}<<"
>>abcdefg<<

正規表現は完全なPCREではなく拡張正規表現です。

関連情報