sedキャプチャグループが機能しない


27

私はフォーマットの文字列を持っています[0-9]+\.[0-9]+\.[0-9]。最初、2番目、3番目の数字を別々に抽出する必要があります。私が理解しているように、キャプチャグループにはこれが可能なはずです。私はsed "s/\([0-9]*\)/\1/g、最初の番号sed "s/\([0-9]*\)/\2/gを取得し、2番目の番号sed "s/\([0-9]*\)/\3/gを取得し、3番目の番号を取得するために使用できるはずです。ただし、それぞれの場合、文字列全体を取得しています。なんでこんなことが起こっているの?


6
キャプチャグループは、グループ内の個々の要素ではなく、グループ全体をキャプチャします。's/\([0-9]\)\([0-9]\)\([0-9]\).*/\1\2\3/'個々の番号をキャプチャするようなものが必要です。
ムニール

回答:


45

入力例を挙げずに完全な答えを出すことはできませんが、キャプチャグループの理解が間違っていると言えます。連続して使用するのではなく、同じ置換演算子の左側の正規表現のみを参照します。たとえば、キャプチャする場合/(foo)(bar)(baz)/、はfooになり\1barになり\2、にbazなります\3。できませんs/(foo)/\1/; s/(bar)/\2/。2回目のs///呼び出しでは、キャプチャされたグループは1つだけなので、\2定義されません。

したがって、数字の3つのグループをキャプチャするには、次の操作を行う必要があります。

sed 's/\([0-9]*\)\.\([0-9]*\)\.\([0-9]*\)/\1 : \2 : \3/'

または、より読みやすい:

sed -E 's/([0-9]*)\.([0-9]*)\.([0-9]*)/\1 : \2 : \3/'

1
最初の例の括弧をエスケープすることの利点は何ですか?
ジョシュM.

2
@JoshM。パターンをキャプチャするために使用するには、それらをエスケープする必要があります。通常/(foo)/、sedではリテラル(文字に一致しfoo、その後にリテラルが続き)ます。グループをキャプチャする場合は、括弧をエスケープするか、-Eオプションを使用する必要があります。
テルドン

私はほとんど常にこの-rフラグを使用しているので、まだこれに遭遇していないのだと思います。
ジョシュM.

1
@JoshM。はい、-rフラグもそれを行いますが、移植性はありません。GNU sedはサポートしていますが、他の多くはサポートしていません。-Eより普遍的です。
テルドン

9

例:

$ echo "123.456.78" |sed 's/\([0-9]*\)\.\([0-9]*\)\.\([0-9]*\)/\1/'
123

$ echo "123.456.78" |sed 's/\([0-9]*\)\.\([0-9]*\)\.\([0-9]*\)/\2/'
456

$ echo "123.456.78" |sed 's/\([0-9]*\)\.\([0-9]*\)\.\([0-9]*\)/\3/'
78

または、すべて一緒に:

$ echo "123.456.78" |sed 's/\([0-9]*\)\.\([0-9]*\)\.\([0-9]*\)/\1 : \2 : \3/'
123 : 456 : 78

2

-r、-regexp-extendedとともにSedを使用して、エスケープされたすべての括弧を回避します。

echo "1234.567.89" | sed -r 's/([0-9]+)\.([0-9]+)\.([0-9]+)/\1, \2, \3/' 
1234, 567, 89    #output
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.