我正在尝试创建一个正则表达式字符类,它匹配仅包含一个或多个以下字符的字符串,并且不包含任何其他字符。
:
a
l
p
h
。当然,我可以做这样简单的事情并且有效。
$ printf "foo\nhal\npal\na:h\n" | grep '^[:alph]*$'
hal
pal
a:h
但是如果我尝试做这样的事情,即在字符类中使用冗余字符,我会收到错误。
$ printf "foo\nhal\npal\na:h\n" | grep '^[:alpha:]*$'
grep: character class syntax is [[:space:]], not [:space:]
现在,我知道发生了什么。 grep
"相信"当我的意思是[:alpha:]
时,我错误地写了[[:alpha:]]
。
但是不是[:alpha:]
POSIX中有效的正则表达式吗?它是否真的会为有效的正则表达式抛出错误?我不应该警告我,我的意思是[[:alpha:]]
吗?
事实上,如果我在正则表达式中使用sed
,[:alpha:]
根本就不会抱怨。它的行为与[:alph]
完全相同。我相信sed
做对了。
$ printf "foo\nhal\npal\na:h\n" | sed -n '/^[:alpha]*$/p'
hal
pal
a:h
Python也做对了。
>>> import re
>>> re.search('^[:alpha:]*$', 'foo')
>>> re.search('^[:alpha:]*$', 'hal')
<_sre.SRE_Match object at 0x7f33d4060f38>
>>> re.search('^[:alpha:]*$', 'pal')
<_sre.SRE_Match object at 0x7f33d4060920>
>>> re.search('^[:alpha:]*$', 'a:h')
<_sre.SRE_Match object at 0x7f33d4060f38>
只有grep
试图变得聪明并告诉我,我并不是[:alpha:]
,而是指[[:alpha:]]
。
关于它的POSIX标准是什么?是否允许正则表达式引擎为[:alpha:]
引发错误,或者它是否需要引擎将[:alpha:]
视为[:alph]
?
如果可以逐字引用POSIX标准的相关摘录及其网址,我会认为我的问题已得到解答。
答案 0 :(得分:5)
你是对的,“grep
[正在努力]聪明并告诉我,我不是指[:alpha:]
,而是我的意思是[[:alpha:]]
”就个人而言,我不喜欢我认为这是一件非常糟糕的事情 - 如果grep
在表达式中看到[:alpha:]
,我会说编写它的人更有可能犯错,而不是实际意味着是什么严格写。
你也是对的,这个(可以说是有帮助的)行为不是conform to POSIX。我注意到,GNU grep
受环境变量POSIXLY_CORRECT
的影响,它改变了它的行为,使其符合POSIX标准。还有note on the man page表示:
如果你错误地省略了外括号,并搜索说, '
[:upper:]
',GNU grep打印诊断并退出状态为2 假设您不打算在名义上搜索 等价正则表达式:'[:epru]
'。设置POSIXLY_CORRECT
环境变量以禁用此功能。
比较
$ printf "foo\nhal\npal\na:h\n" | grep '^[:alpha:]*$'
grep: character class syntax is [[:space:]], not [:space:]
与
$ printf "foo\nhal\npal\na:h\n" | POSIXLY_CORRECT=1 grep '^[:alpha:]*$'
hal
pal
a:h
如果您 不想要它,看起来好像可以关闭这种“有用”的行为。