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


17

bashで、文字列があると仮定しますstrname

strname="ph7go04325r"

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

strresult="25"

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

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

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

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

回答:


28

これを実現するには、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には最初のキャプチャグループの一致が含まれます。


10

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

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

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

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

古いとはexprマッチが失敗した場合はゼロ以外の終了ステータス(罰金)を取得することですが、あなたも(と同じように返される文字列の解決された場合、0にゼロ以外の終了ステータスを取得しますstrname=zz300rzz)。


あなたの言い回しは、これはbashの古いバージョンでしかできないことを間違って暗示していると思います。もちろん、パラメーターの拡張は、現代のシェルでは依然として優れたアプローチです。
小次郎

1
@kojiro、どういう意味かわかります。最初の定式化は、ヨルダンの答えをフォローアップすることでした。回答を更新しました。
ステファンシャゼル
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.