![为什么 '[az]*' 匹配非字母字符串?](https://linux22.com/image/133778/%E4%B8%BA%E4%BB%80%E4%B9%88%20'%5Baz%5D*'%20%E5%8C%B9%E9%85%8D%E9%9D%9E%E5%AD%97%E6%AF%8D%E5%AD%97%E7%AC%A6%E4%B8%B2%EF%BC%9F.png)
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'