当我的意思是`[:alph]`时,grep不允许我写`[:alpha:]`但是其他工具呢

时间:2014-09-21 15:02:16

标签: python regex sed grep posix

我正在尝试创建一个正则表达式字符类,它匹配仅包含一个或多个以下字符的字符串,并且不包含任何其他字符。

  • :
  • 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标准的相关摘录及其网址,我会认为我的问题已得到解答。

1 个答案:

答案 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

如果您 不想要它,看起来好像可以关闭这种“有用”的行为。