为什么 '[az]*' 匹配非字母字符串?

为什么 '[az]*' 匹配非字母字符串?

alphanum我有一个包含这两行的文件:

123 abc
this is a line

我很困惑为什么当我运行时sed 's/[a-z]*/SUB/' alphanum,我得到以下输出:

SUB123 abc
SUB is a line

我期待着:

123 SUB
SUB is a line

我找到了一个修复(sed 's/[a-z][a-z]*/SUB/'改为使用),但我不明白为什么它有效而我的却不起作用。

你能帮我吗?

答案1

模式[a-z]*匹配a或范围内的多个字符z实际的字符取决于当前区域设置)。在字符串的开头有零个这样的字符123 abc(即模式匹配),在 的开头也有四个这样的字符this is a line

如果你至少需要匹配,然后使用[a-z][a-z]*or ,或者使用 和 use[a-z]\{1,\}启用扩展正则表达式。sed -E[a-z]+

要可视化模式匹配的位置,请在每个匹配项周围添加括号:

$ sed 's/[a-z]*/(&)/' file
()123 abc
(this) is a line

或者,查看各行中的所有匹配项:

$ sed 's/[a-z]*/(&)/g' file
()1()2()3() (abc)
(this) (is) (a) (line)

将最后的结果与

$ sed -E 's/[a-z]+/(&)/g' file
123 (abc)
(this) (is) (a) (line)

答案2

因为*匹配零个或多个重复前一个原子,并且所有正则表达式引擎都会尝试找到第一个匹配项。字符串开头有一个恰好为零个字母的子字符串,因此这就是它匹配的位置。在字符串以字母开头的情况下,会*尽可能多地匹配,但这对于查找最左边的匹配来说是次要的。

零长度匹配可能有点问题,正如您所见,解决方案是修改模式,使其至少需要一个字符。使用扩展的正则表达式,您可以+sed -E 's/[a-z]+/SUB/'

为了好玩,请尝试:

echo 'less than 123 words' | sed 's/[0-9]*/x/g'

相关内容