sed捕获组不起作用


27

我有一个格式为的字符串[0-9]+\.[0-9]+\.[0-9]。我需要分别提取第一个,第二个和第三个数字。据我了解,捕获组应该能够做到这一点。我应该可以sed "s/\([0-9]*\)/\1/g用来取得第一个号码,sed "s/\([0-9]*\)/\2/g获取第二个数字以及sed "s/\([0-9]*\)/\3/g获取第三个数字。但是,在每种情况下,我都会得到整个字符串。为什么会这样呢?


6
捕获组捕获整个组,而不是捕获组中的单个元素。您需要's/\([0-9]\)\([0-9]\)\([0-9]\).*/\1\2\3/'获取单个数字的方法。
Munir

Answers:


45

没有输入示例,我们无法为您提供完整的答案,但是我可以告诉您,您对捕获组的理解是错误的。您无需顺序使用它们,它们仅引用同一替换运算符左侧的regex。例如,如果您捕获,/(foo)(bar)(baz)/foo将会是\1bar将会是\2baz将是\3。您无法执行此操作s/(foo)/\1/; s/(bar)/\2/,因为在第二个s///调用中,只有一个捕获的组,因此\2不会定义。

因此,要捕获三组数字,您需要执行以下操作:

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选项。
terdon

我几乎总是使用该-r标志,所以我认为这就是为什么我还没有遇到这个问题。
乔什·M

1
@JoshM。是的,该-r标志也可以这样做,但是它不是可移植的。GNU sed支持它,但许多其他人不支持。这-E是更普遍的。
terdon

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
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.