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

Lon*_*ner 1 python regex grep posix sed

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

  • :
  • a
  • l
  • p
  • h.

当然,我可以做这样简单的事情并且有效.

$ printf "foo\nhal\npal\na:h\n" | grep '^[:alph]*$'
hal
pal
a:h
Run Code Online (Sandbox Code Playgroud)

但是如果我尝试做这样的事情,即在字符类中使用冗余字符,我会收到错误.

$ printf "foo\nhal\npal\na:h\n" | grep '^[:alpha:]*$'
grep: character class syntax is [[:space:]], not [:space:]
Run Code Online (Sandbox Code Playgroud)

现在,我知道发生了什么.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
Run Code Online (Sandbox Code Playgroud)

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>
Run Code Online (Sandbox Code Playgroud)

它只是grep试图变得聪明并告诉我,我不是故意[:alpha:],而是我的意思[[:alpha:]].

POSIX标准是什么?是否允许正则表达式引擎抛出了一个错误[:alpha:]还是需要发动机对待[:alpha:],就像它是[:alph]

如果可以逐字引用POSIX标准的相关摘录以及它的URL,我会考虑回答我的问题.

Tim*_*Tim 5

你是对的," grep[正在努力]变得聪明并告诉我,我不是故意[:alpha:],而是我的意思是[[:alpha:]]"个人而言,我认为这不是一件非常糟糕的事情 - 如果在表达中grep看到[:alpha:],我会说写作的人更有可能犯了错误,而不是真正意味着严格写的.

你也是对的,这个(可以说是有帮助的)行为不符合POSIX.我注意到,GNU grep受环境变量的影响,该变量POSIXLY_CORRECT改变了它的行为,使其符合POSIX标准.手册页上还有一条说明:

如果错误地省略了外架,并搜索说," [:upper:]",GNU的grep打印诊断和退出时的状态2,在您不打算寻找名义上相当于正则表达式的假设:" [:epru]".设置POSIXLY_CORRECT 环境变量以禁用此功能.

相比:

$ printf "foo\nhal\npal\na:h\n" | grep '^[:alpha:]*$'
grep: character class syntax is [[:space:]], not [:space:]
Run Code Online (Sandbox Code Playgroud)

用.

$ printf "foo\nhal\npal\na:h\n" | POSIXLY_CORRECT=1 grep '^[:alpha:]*$'
hal
pal
a:h
Run Code Online (Sandbox Code Playgroud)

因此,如果您真的不想要它,看起来好像可以关闭这种"有用"的行为.