为什么没有“?” 正则表达式字符在 sed 中产生匹配?

maz*_*azs 8 sed regular-expression

我有一个类似于../../sdd1并试图sdd从这里匹配的字符串。我正在尝试使用以下sed命令:

echo "../../sdd1" | sed 's:.*\([a-z]\{3\}\)[0-9]?:\1:' 
Run Code Online (Sandbox Code Playgroud)

它不会产生匹配。
但是当我使用

echo "../../sdd1" | sed 's:.*\([a-z]\{3\}\)[0-9]\{0,1\}:\1:'
Run Code Online (Sandbox Code Playgroud)

然后我得到了我的比赛,sdd

我最好的猜测是我也应该转义?,类似于大括号 - 我试过它并且它有效,但我不知道为什么。

所以问题是,为什么[0-9]?正则表达式与1from不匹配sdd1,或者为什么我们必须转义 the?和大括号?

Sun*_*eep 17

默认情况下,sed使用 BRE 并且需要-E-r选择使用 ERE

引用GNU sed 手册

在 GNU sed 中,基本正则表达式和扩展正则表达式的唯一区别在于一些特殊字符的行为:“?”、“+”、括号、大括号 (“{}”) 和“|”。

使用基本 (BRE) 语法,这些字符没有特殊含义,除非带有前缀反斜杠 ('\');而扩展 (ERE) 语法则相反:这些字符是特殊的,除非它们以反斜杠 ('\') 为前缀。

所以,对于GNU sed,使用

$ echo '../../sdd1' | sed 's:.*\([a-z]\{3\}\)[0-9]\?:\1:'
sdd
$ echo '../../sdd1' | sed -E 's:.*([a-z]{3})[0-9]?:\1:'
sdd
Run Code Online (Sandbox Code Playgroud)

对于POSIX BRE,你的第二个命令是要走的路

$ echo '../../sdd1' | sed 's:.*\([a-z]\{3\}\)[0-9]\{0,1\}:\1:'
sdd
Run Code Online (Sandbox Code Playgroud)