web-dev-qa-db-ja.com

sedで正規表現[0-9] {0,2}が貪欲でないのはなぜですか?

echo '123980925sriten34=ienat' | sed -e 's/^.*\?\([1-9][0-9]\{0,2\}\+\)\([%=+-]\).*/ \1 \2 /'

結果を出している:

 4 =

私は期待している:

 34 =

何がわからないの?

(ああ、私は+および?二重に確認しますが、afaik {0,2}は、それらなしでは貪欲でなければなりません。)

3
runrin

問題は steeldriverの状態 であり、[0-9]{0,2}が貪欲ではないということではありません。問題は、貪欲になる前の.*?です。 sedはBREとEREをサポートしていますが、どちらも貪欲でないマッチングをサポートしていません。これがPCREの機能です。たとえば、次のコマンド:

$ echo 'aQbQc' | sed    's/.*\?Q/X/'
$ echo 'aQbQc' | sed    's/.*Q/X/'
$ echo 'aQbQc' | sed -r 's/.*?Q/X/'
$ echo 'aQbQc' | sed -r 's/.*Q/X/'

すべての出力

Xc

(なぜ?を無視するのかわかりません。)

SED正規表現による貪欲でない一致(Perlの.*?をエミュレート) を参照してください。

実行したい機能の説明はわかりにくいですが、私はそれをリバースエンジニアリングしたと思います。一致する番号の前の文字を一致させないことで、目的の効果を得ることができます。

$ echo '123980925sriten34=ienat' | sed -e 's/\([1-9][0-9]\{0,2\}\+\)\([%=+-]\).*/! \1 \2 /' -e 's/.*!//'
 34 =

!を、入力データに表示されないことがわかっている文字列に置き換えます。そのような文字列がないが、GNU sedを使用している場合は、改行を使用できます。

$ echo '123980925sriten34=ienat' | sed -e 's/\([1-9][0-9]\{0,2\}\+\)\([%=+-]\).*/\n \1 \2 /' -e 's/.*\n//'
 34 =

もちろん、これはinのどの行にも表示されません。