sed 和捕获组的斗争

Rhy*_*Ink 2 sed regular-expression

我有一个看起来像这样的文本文件

(111)1111111
(111)-111-1111
(111)111-1111
111.111.1111
Run Code Online (Sandbox Code Playgroud)

我用来练习使用正则表达式和 sed 进行组捕获。我在文件上运行的命令(称为测试)是

sed 's/(?\(\d(3}\)[-.]?\(\d{3}\)[-.]?\(\d{4}\)/\1\2\3' test > output
Run Code Online (Sandbox Code Playgroud)

期望每一行的输出都是 1。但是,我得到的只是整个文件,没有任何更改。怎么了?

ilk*_*chu 9

在标准基本正则表达式中,(?\(\d(3}\)[-.]?表示:

a literal left parenthesis
a literal question mark
(start of a group)
a literal character 'd'
a literal left parenthesis 
the number '3'
a literal closing brace
(end of group)
a dash or a dot
a question mark
Run Code Online (Sandbox Code Playgroud)

即,这将打印x

echo '(?d(3}-?' |sed 's/(?\(\d(3}\)[-.]?/x/'
Run Code Online (Sandbox Code Playgroud)

您很可能希望sed -E启用扩展正则表达式 (ERE),然后使用(and)进行分组,以及使用\(and\)进行文字括号。

另请注意,这\d是 Perl 正则表达式的一部分,而不是标准的,虽然 GNU sed 支持一些转义,但它们不是标准的(我认为它不支持)。同样,GNU sed 在 BRE 中支持它以表示ERE 中的含义,但它不是标准的。\X\d\??

考虑到所有这些:

$ echo '(123)-456-7890' | sed -E 's/\(?([0-9]{3})\)?[-.]?([0-9]{3})[-.]?([0-9]{4})/\1\2\3/'
1234567890
Run Code Online (Sandbox Code Playgroud)

尽管您几乎也可以暴力破解它并删除除数字之外的所有内容:

$ echo '(123)-456-7890' | sed -e 's/[^0-9]//g'
1234567890
Run Code Online (Sandbox Code Playgroud)

(当然也可以接受类似的东西(123)-4.5-6-7a8b9c0......)

也可以看看: