Sed 和捕获组的斗争

Sed 和捕获组的斗争

我有一个如下所示的文本文件

(111)1111111
(111)-111-1111
(111)111-1111
111.111.1111

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

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

期望输出每行全为 1。但是,我得到的只是整个文件,没有任何更改。出了什么问题?

答案1

在标准基本正则表达式中,(?\(\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

即,这将打印x

echo '(?d(3}-?' |sed 's/(?\(\d(3}\)[-.]?/x/'

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

另请注意,这\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

尽管您也可能只是暴力破解它并删除除数字之外的所有内容:

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

(这当然也会接受诸如(123)-4.5-6-7a8b9c0...之类的东西)

也可以看看:

答案2

我们也可以在 awk 命令下完成

echo "123-45-6789-10101"| awk '{gsub("[^0-9]","",$1);print }'

输出

12345678910101

答案3

伊尔卡丘描述很好为什么你的正则表达式不起作用sed(它是不支持的方言)。

这是另一种方法,仅删除不存在的字符1

sed 's/[^1]//g' file

要使用组,您可以执行类似的操作

sed -E 's/([^1]*)(1+)([^1]*)/\2/g' file

也就是说,匹配两侧可能为空的非 1 字符串分隔的非空 1 字符串,并将所有内容替换为匹配的 1 字符串。

更改1[0-9][^1]to[^0-9]以处理所有数字。

相关内容