Yes, it is [[:digit:]]
~ [0-9]
~ \d
(where ~ means approximate).
In most programming languages (where it is supported)
\d ≡ `[[:digit:]]` # (is identical to, it is a short hand for).
The \d
exists in less instances than [[:digit:]]
(available in grep -P
but not in POSIX).
Unicode digits
There are many digits in UNICODE, for example:
123456789 # Hindu-Arabic
Arabic numerals
٠١٢٣٤٥٦٧٨٩ # ARABIC-INDIC
۰۱۲۳۴۵۶۷۸۹ # EXTENDED ARABIC-INDIC/PERSIAN
߀߁߂߃߄߅߆߇߈߉ # NKO DIGIT
०१२३४५६७८९ # DEVANAGARI
All of which may be included in [[:digit:]]
or \d
, and even some cases of [0-9]
.
POSIX
For the specific POSIX BRE or ERE:
The \d
is not supported (not in POSIX but is in GNU grep -P
).
[[:digit:]]
is required by POSIX to correspond to the digit character class, which in turn is required by ISO C to be the characters 0 through 9 and nothing else. So only in C locale all [0-9]
, [0123456789]
, \d
and [[:digit:]]
mean exactly the same. The [0123456789]
has no possible misinterpretations, [[:digit:]]
is available in more utilities and in some cases mean only [0123456789]
. The \d
is supported by few utilities.
As for [0-9]
, the meaning of range expressions is only defined by POSIX in the C locale; in other locales it might be different (might be codepoint order or collation order or something else).
[0123456789]
The most basic option for all ASCII digits.
Always valid, (AFAICT) no known instance where it fails.
It match only English Digits: 0123456789
.
[0-9]
It is generally believed that [0-9]
is only the ASCII digits 0123456789
.
That is painfully false in some instances: Linux in some locale that is not "C" (June of 2020) systems, for example:
Assume:
str='0123456789 ٠١٢٣٤٥٦٧٨٩ ۰۱۲۳۴۵۶۷۸۹ ߀߁߂߃߄߅߆߇߈߉ ०१२३४५६७८९'
Try grep
to discover that it allows most of them:
$ echo "$str" | grep -o '[0-9]\+'
0123456789
٠١٢٣٤٥٦٧٨
۰۱۲۳۴۵۶۷۸
߀߁߂߃߄߅߆߇߈
०१२३४५६७८
That sed has some troubles. Should remove only 0123456789
but removes almost all digits. That means that it accepts most digits but not some nine's (???):
$ echo "$str" | sed 's/[0-9]\{1,\}//g'
٩ ۹ ߉ ९
That even expr suffers of the same issues of sed:
expr "$str" : '\([0-9 ]*\)' # also matching spaces.
0123456789 ٠١٢٣٤٥٦٧٨
And also ed
printf '%s\n' 's/[0-9]/x/g' '1,p' Q | ed -v <(echo "$str")
105
xxxxxxxxxx xxxxxxxxx٩ xxxxxxxxx۹ xxxxxxxxx߉ xxxxxxxxx९
[[:digit:]]
There are many languages: Perl, Java, Python, C. In which [[:digit:]]
(and \d
) calls for an extended meaning. For example, this perl code will match all the digits from above:
$ str='0123456789 ٠١٢٣٤٥٦٧٨٩ ۰۱۲۳۴۵۶۷۸۹ ߀߁߂߃߄߅߆߇߈߉ ०१२३४५६७८९'
$ echo "$str" | perl -C -pe 's/[^\d]//g;' ; echo
0123456789٠١٢٣٤٥٦٧٨٩۰۱۲۳۴۵۶۷۸۹߀߁߂߃߄߅߆߇߈߉०१२३४५६७८९
Which is equivalent to select all characters that have the Unicode properties of Numeric
and digits
:
$ echo "$str" | perl -C -pe 's/[^\p{Nd}]//g;' ; echo
0123456789٠١٢٣٤٥٦٧٨٩۰۱۲۳۴۵۶۷۸۹߀߁߂߃߄߅߆߇߈߉०१२३४५६७८९
Which grep could reproduce (the specific version of pcre may have a different internal list of numeric code points than Perl):
$ echo "$str" | grep -oP '\p{Nd}+'
0123456789
٠١٢٣٤٥٦٧٨٩
۰۱۲۳۴۵۶۷۸۹
߀߁߂߃߄߅߆߇߈߉
०१२३४५६७८९
shells
Some implementations may understand a range to be something different than plain ASCII order (ksh93 for example) (when tested on May 2018 version (AT&T Research) 93u+ 2012-08-01):
$ LC_ALL=en_US.utf8 ksh -c 'echo "${1//[0-9]}"' sh "$str"
۹ ߀߁߂߃߄߅߆߇߈߉ ९
Now (June 2020), the same package ksh93 from debian (same version sh (AT&T Research) 93u+ 2012-08-01):
$ LC_ALL=en_US.utf8 ksh -c 'echo "${1//[0-9]}"' sh "$str"
٩ ۹ ߉ ९
And that seems to me as a sure source of bugs waiting to happen.