web-dev-qa-db-ja.com

bashスクリプトでパターンに従って文字列を抽出する

Bashでは、文字列strnameがあるとします。

strname="ph7go04325r"

first"3"文字とstrnameの-​​last"r"文字の間の文字を抽出して結果を保存したい文字列strresult。上記の例では、結果のstrresultは次のようになります。

strresult="25"

最初の"3"文字はnotで、必ずstrnameの文字列位置8にあります。同様に、最後の"r"notであり、文字列位置11である必要があります。したがって、次の文字列strnameは両方ともstrresult="25"になるはずです。

strname="ph11go04325raa"
strname="325r"
strname="rgo04325raa"

また、strname=ph12go04330raa"strresult="30"を生成する必要があります。

私はbashスクリプトに慣れていないので、このような文字列パターンマッチングをどこから始めればよいかわかりません。何か提案はありますか?

17
Andrew

これを行うには、bash(3.0以降)で正規表現を使用できます。

if [[ $strname =~ 3(.+)r ]]; then
    strresult=${BASH_REMATCH[1]}
else
    echo "unable to parse string $strname"
fi

Bashでは、正規表現からのキャプチャグループが特別な配列BASH_REMATCHに配置されます。要素0には一致全体が含まれ、1には最初のキャプチャグループの一致が含まれます。

31
jordanm

標準のsh構文では(bashのすべてのバージョンまたは他のPOSIX準拠のシェルで機能するため)、次のようにします。

case $strname in
  (*3*r*) 
    strresult=${strname#*3}
    strresult=${strresult%r*};;
  (*)
    printf >&2 '%s\n' "Unable to parse string $strname"
esac

35歳のUnicesでも動作する古いexprソリューションも参照してください。

expr "x$strname" : 'x[^3]*3\(.*\)r'

exprでの古いquirkは、一致が失敗した場合にゼロ以外の終了ステータス(正常)を取得しますが、返された文字列が解決された場合にもゼロ以外の終了ステータスを取得します0(strname=zz300rzzなど)。

10