Wikipediaの正規表現に関する記事 では、[[:digit:]]
= [0-9]
= \d
。
それらが等しくない状況は何ですか?違いはなんですか?
いくつか調査した結果、1つの違いはブラケット式[:expr:]
はロケールに依存します。
はい、それは[[:digit:]]
〜[0-9]
〜\d
です(ここで〜は概算を意味します)。
ほとんどのプログラミング言語(サポートされている場合)\d
≡[[:digit:]]
(同一)。\d
は[[:digit:]]
より一般的ではありません(POSIXにはありませんが、GNU grep -P
にあります)。
NICODEの多くの数字 があります。次に例を示します。
123456789 # Hindu-Arabic
アラビア数字٠١٢٣٤٥٦٧٨٩ # ARABIC-INDIC
۰۱۲۳۴۵۶۷۸۹ # EXTENDED ARABIC-INDIC/PERSIAN
߀߁߂߃߄߅߆߇߈߉ # NKO DIGIT
०१२३४५६७८९ # DEVANAGARI
すべて 含まれる場合があります[[:digit:]]
または\d
内。
代わりに、[0-9]
は通常、ASCII digits 0123456789
のみです。
Perl、Java、Python、Cなど、多くの言語があります。ここで、[[:digit:]]
(および\d
)は拡張された意味を要求します。たとえば、次のPerlコードは上記のすべての数字と一致します。
$ a='0123456789 ٠١٢٣٤٥٦٧٨٩ ۰۱۲۳۴۵۶۷۸۹ ߀߁߂߃߄߅߆߇߈߉ ०१२३४५६७८९'
$ echo "$a" | Perl -C -pe 's/[^\d]//g;' ; echo
0123456789٠١٢٣٤٥٦٧٨٩۰۱۲۳۴۵۶۷۸۹߀߁߂߃߄߅߆߇߈߉०१२३४५६७८९
これは、Numeric
およびdigits
のUnicodeプロパティを持つすべての文字を選択することと同じです。
$ 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]}"'
۹ ߀߁߂߃߄߅߆߇߈߉ ९
そして、それは発生するのを待っているバグの確かな原因です。
これは、数字の定義方法によって異なります。 [0-9]
は、ASCII ones(またはおそらくASCIIでもASCIIのスーパーセットでもないASCII異なるビット表現の場合のみ(EBCDIC))と同じ10桁。一方、\d
は、単なる数字(古いバージョンのPerl、または最新バージョンのPerl /a
正規表現フラグが有効)または、\p{Digit}
または[0-9]
一致よりも数字のセットが大きい/\d/a
のUnicode一致である可能性があります。
$ 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]
も含まれます。これは、Cでのisdigit(3)
([0-9]
)とisnumber(3)
([0-9
とロケールの他のすべての違い)の違いに似ています。
[0-9]
でなくても、桁の値を取得するために呼び出される可能性があります。
$ Perl -MUnicode::UCD=num -E 'say num(4)'
4
$ Perl -MUnicode::UCD=num -E 'say num("\N{U+09EA}")'
4
$
他の回答では、[0-9]
、[[:digit:]]
、\d
の意味が異なります。ここでは、正規表現エンジンの実装に違いを追加したいと思います。
[[:digit:]] \d
grep -E ✓ ×
grep -P ✓ ✓
sed ✓ ×
sed -E ✓ ×
したがって、[[:digit:]]
は常に機能します、\d
によって異なります。 grepのマニュアルでは、C
ロケールでは[[:digit:]]
が0-9
であると記載されています。
PS1:詳しくは、表を展開してください。
PS2:GNU grep 3.1およびGNU 4.4がテストに使用されます。
理論的な違いはすでに他の回答でかなりよく説明されているので、実用的な違いを説明することは残ります。
次に、数字を照合するためのより一般的な使用例をいくつか示します。
多くの場合、いくつかの数値をクランチしたい場合、数値自体が扱いにくい形式のテキストファイルに含まれています。それらをプログラムで使用するために抽出したいとします。 (ファイルを見れば)数値形式と現在のロケールがわかるので、ジョブが実行される限り、任意の形式を使用しても問題ありませんです。 \d
必要なキーストロークが最も少ないため、非常に一般的に使用されます。
信頼できないユーザー入力(おそらくWebフォームから)があり、サプライズが含まれていないことを確認する必要があります。それをデータベースの数値フィールドに格納したり、サーバーで実行するシェルコマンドのパラメーターとして使用したりすることができます。この場合、あなたは本当に欲しい[0-9]
、これは最も制限があり予測可能なものだからです。
「危険」なものには何も使用しないデータが少しありますが、それが数値であるかどうかを知っておくと便利です。たとえば、プログラムでユーザーが住所を入力できるようにし、入力に家の番号が含まれていない場合に、入力ミスの可能性を強調したいとします。この場合、おそらくできるだけ広くしたいので、[[:digit:]]
を使用する方法です。
これらは、数字照合の最も一般的な3つの使用例のようです。重要なものを逃したと思われる場合は、コメントをドロップしてください。