![Sed 和捕获组的斗争](https://linux22.com/image/132117/Sed%20%E5%92%8C%E6%8D%95%E8%8E%B7%E7%BB%84%E7%9A%84%E6%96%97%E4%BA%89.png)
我有一个如下所示的文本文件
(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]
以处理所有数字。