在Wikipedia关于正则表达式的文章中,似乎[[:digit:]]
= [0-9]
= \d
。
在什么情况下它们不相等?有什么不同?
经过一番研究,我认为其中的一个区别是方括号表达[:expr:]
是区域性的。
在Wikipedia关于正则表达式的文章中,似乎[[:digit:]]
= [0-9]
= \d
。
在什么情况下它们不相等?有什么不同?
经过一番研究,我认为其中的一个区别是方括号表达[:expr:]
是区域性的。
Answers:
是的,这是[[:digit:]]
〜[0-9]
〜\d
(这里〜手段aproximate)。
在大多数的编程语言(它支持)\d
≡ [[:digit:]]
(相同)。
与\d
相比[[:digit:]]
,它不那么常见(不是在POSIX中,而是在GNU中grep -P
)。
123456789 # Hindu-Arabic
阿拉伯数字
٠١٢٣٤٥٦٧٨٩ # ARABIC-INDIC
۰۱۲۳۴۵۶۷۸۹ # EXTENDED ARABIC-INDIC/PERSIAN
߀߁߂߃߄߅߆߇߈߉ # NKO DIGIT
०१२३४५६७८९ # DEVANAGARI
所有这些都可以包含在[[:digit:]]
或中\d
。
相反,[0-9]
通常只有ASCII数位0123456789
。
有许多语言:Perl,Java,Python和C。其中[[:digit:]]
(和\d
)要求扩展的含义。例如,此Perl代码将匹配上面的所有数字:
$ a='0123456789 ٠١٢٣٤٥٦٧٨٩ ۰۱۲۳۴۵۶۷۸۹ ߀߁߂߃߄߅߆߇߈߉ ०१२३४५६७८९'
$ echo "$a" | perl -C -pe 's/[^\d]//g;' ; echo
0123456789٠١٢٣٤٥٦٧٨٩۰۱۲۳۴۵۶۷۸۹߀߁߂߃߄߅߆߇߈߉०१२३४५६७८९
这相当于选择具有的Unicode属性所有字符Numeric
和digits
:
$ echo "$a" | perl -C -pe 's/[^\p{Nd}]//g;' ; echo
0123456789٠١٢٣٤٥٦٧٨٩۰۱۲۳۴۵۶۷۸۹߀߁߂߃߄߅߆߇߈߉०१२३४५६७८९
哪个grep可以复制(特定版本的pcre可能与Perl相比具有不同的内部数字代码点列表):
$ echo "$a" | grep -oP '\p{Nd}+'
0123456789
٠١٢٣٤٥٦٧٨٩
۰۱۲۳۴۵۶۷۸۹
߀߁߂߃߄߅߆߇߈߉
०१२३४५६७८९
将其更改为[0-9]以查看:
$ echo "$a" | grep -o '[0-9]\+'
0123456789
对于具体POSIX BRE或ERE:
在\d
不支持(不属于POSIX但在GNU grep -P
)。
[[:digit:]]
POSIX要求将其与数字字符类相对应,而数字字符类又由ISO C要求是字符0到9,而没有其他字符。因此,只有在C语言环境所有[0-9]
,[0123456789]
,\d
和[[:digit:]]
平均一模一样。在[0123456789]
没有可能的误解,[[:digit:]]
是更多的实用程序可用,但通常仅意味[0123456789]
。该\d
由几个实用程序支持。
至于[0-9]
范围表达式的含义仅由C语言环境中的POSIX定义; 在其他语言环境中,它可能有所不同(可能是代码点顺序或排序规则顺序或其他)。
一些实现可能将范围理解为与纯ASCII顺序(例如ksh93)不同:
$ LC_ALL=en_US.utf8 ksh -c 'a="'"$a"'";echo "${a//[0-9]}"'
۹ ߀߁߂߃߄߅߆߇߈߉ ९
这肯定是等待发生错误的来源。
iswctype()
和POSIX实用程序中的BRE / ERE /通配符上,[0-9]和[[:digit:]]仅与0123456789匹配。而将要进行标准的下一版本明确
perl
的\d
关于从其他脚本十进制数字匹配Unicode模式。感谢那。对于PCRE,请参见(*UCP)
GNU中的内容,grep -Po '(*UCP)\d'
或者grep -Po '(*UCP)[[:digit:]]
使类基于Unicode属性。
[:digit:]
语法建议您使用本地化,即用户认为是数字的任何内容。我从不使用,[:digit:]
因为在实践[0-9]
中无论如何我总是要匹配0123456789,在任何情况下我都想匹配,我从不打算匹配٠١٢٣٤٥٦٧٨٩
,并且我想不出一个用例要匹配十进制数字的用例在任何带有POSIX实用程序的脚本中。另请参阅有关[:blank:]
zsh ML的当前讨论。这些字符类有点混乱。
这取决于您如何定义数字。[0-9]
往往只是ASCII码(或其他可能既不是ASCII也不是ASCII的超集,但与ASCII相同的10位数字,只是具有不同的位表示形式(EBCDIC));\d
另一方面,可以是纯数字(Perl的旧版本,或者/a
启用了正则表达式标志的Perl的现代版本),也可以是Unicode匹配,\p{Digit}
而Unicode匹配则比[0-9]
or 更大/\d/a
。
$ perl -E 'say "match" if 42 =~ m/\d/'
match
$ perl -E 'say "match" if "\N{U+09EA}" =~ m/\d/'
match
$ perl -E 'say "match" if "\N{U+09EA}" =~ m/\d/a'
$ perl -E 'say "match" if "\N{U+09EA}" =~ m/[0-9]/'
$
perldoc perlrecharclass
有关更多信息,或查阅有关语言的文档以了解其行为。
但是,等等,还有更多!语言环境也可能会改变\d
匹配的内容,因此\d
匹配的位数可能少于此类的完整Unicode集,并且(希望通常是)还包括[0-9]
。这类似于isdigit(3)
([0-9]
)和isnumber(3)
([0-9
再加上语言环境中的其他内容)之间C的差异。
可能会进行调用以获取数字的值,即使不是[0-9]
:
$ perl -MUnicode::UCD=num -E 'say num(4)'
4
$ perl -MUnicode::UCD=num -E 'say num("\N{U+09EA}")'
4
$
[0-9]
。
不同的意义的[0-9]
,[[:digit:]]
而\d
在其他的答案被呈现。在这里,我想补充一下正则表达式引擎实现的差异。
[[:digit:]] \d
grep -E ✓ ×
grep -P ✓ ✓
sed ✓ ×
sed -E ✓ ×
因此[[:digit:]]
始终有效,\d
取决于。在grep的手册中,提到[[:digit:]]
的只是0-9
在C
语言环境中。
PS1:如果您了解更多信息,请扩展表格。
PS2:GNU grep 3.1和GNU 4.4用于测试。
grep
和的版本很多sed
,GNU版本与其他版本之间的最大差异可能很大。如果它提到的是哪个版本这个答案可能会更有用grep
和sed
它是指。或者,该表的来源是什么。2)该表格也可能会转录为文本,因为它不包含任何要求将其作为图像的内容
re
模块不支持[[:digit:]],但是add in库regex
确实支持它,所以我总是会有点儿麻烦。它始终适用于posix投诉情况。
在其他答案中已经很好地解释了理论差异,因此仍然需要解释实际差异。
以下是一些与数字匹配的较常见用例:
通常,当您想处理一些数字时,数字本身位于格式笨拙的文本文件中。您要提取它们以在程序中使用。您可能可以告诉数字格式(通过查看文件)和当前的语言环境,因此可以使用任何形式,只要可以完成工作即可。\d
需要最少的击键,因此非常常用。
您有一些不受信任的用户输入(也许来自Web表单),并且需要确保它不包含任何意外。也许您想将其存储在数据库的数字字段中,或者用作外壳程序命令的参数以在服务器上运行。在这种情况下,您确实想要[0-9]
,因为它是最严格和最可预测的。
您有一些数据不会用于“危险”的事情,但是很高兴知道它是否为数字。例如,您的程序允许用户输入地址,并且如果输入的内容不包含门牌号,则希望突出显示可能的错字。在这种情况下,您可能希望尽可能地广泛,所以[[:digit:]]
方法也应如此。
这些似乎是数字匹配的三个最常见的用例。如果您认为我错过了重要的一个,请发表评论。