Edited at

数値とマッチする正規表現

More than 1 year has passed since last update.


初めに

正規表現を使って数値を検索する機会は多くあると思います。

単純な数値でしたら簡単に検索できます。

しかし、実数や指数表記のものを対象にした場合は、細かい所が上手く行かない事があります。

そこで数値を検索する正規表現をまとめてみたいと思いました。

ここではjavascriptで実行できるものを考えています。

また括弧は全て(?:) 非格納括弧(non-capturing group) を使います。


一覧


  • [+-]?\d+

    整数


  • [+-]?(?:0[xX])?[0-9a-fA-F]+[hH]?

    16進数


  • [+-]?\d+(?:\.\d+)?

    実数(0省略を許さない)


  • [+-]?(?:\d+\.?\d*|\.\d+)

    実数(0省略を許す)


  • [+-]?\d+(?:\.\d+)?(?:[eE][+-]?\d+)?

    e表記の指数表記(0省略を許さない)


  • [+-]?(?:\d+\.?\d*|\.\d+)(?:[eE][+-]?\d+)?

    e表記の指数表記(0省略を許す)


  • [+-]?\d+(?:\.\d+)?(?:(?:[eE][+-]?\d+)|(?:\*10\^[+-]?\d+))?

    10の累乗およびe表記の指数表記(0省略を許さない)


  • [+-]?(?:\d+\.?\d*|\.\d+)(?:(?:[eE][+-]?\d+)|(?:\*10\^[+-]?\d+))?

    10の累乗およびe表記の指数表記(0省略を許す)



整数


  • \d+

  • [+-]?\d+

まずは整数を考えてみます。

これは、単純です。

[0-9]+ もしくは \d+ です。

[0-9]\d は同じことなので、以下では全て \d を使います。

ただ数値には、符号が付くことが有りますのでそのことを考慮しなければいけない事もあります。

そこで符号を考慮した整数用正規表現は、[+-]?\d+ 辺りになるでしょう。


16進数


  • [0-9a-fA-F]+

  • [+-]?(?:0[xX])?[0-9a-fA-F]+[hH]?

次に16進数を考えてみます。

一番単純なものは、[0-9a-fA-F]+ でしょう。

場合によっては接頭辞が付くことが有ります。

接頭辞を考慮すると、(?:0[xX])?[0-9a-fA-F]+ となります。

接尾辞が付くこともあります。

その場合は、[0-9a-fA-F]+[hH]? です。

さらに符号を考慮し全てに対応したものは、[+-]?(?:0[xX])?[0-9a-fA-F]+[hH]? となります。

大文字や小文字のみマッチさせたい場合は、適宜修正してください。


実数


  • \d+(?:\.\d+)?

  • \d+\.?\d*|\.\d+

  • [+-]?\d+(?:\.\d+)?

  • [+-]?(?:\d+\.?\d*|\.\d+)

一番単純なものは、\d+(?:\.\d+)? 辺りでしょうか。

これは以下のようなものにマッチします。

//マッチするもの

123
1.23
12.3

ただし、以下のように小数点の前後の0を省略した場合は、小数点を含みません。

//一部がマッチ

.123
123.

大部分はこれで十分でしょうが、時には0の省略を含めたい事もあります。

そこで改良を考えてみます。

すぐに思いつくのは、 \d*\.?\d* あたりでしょうか。

//マッチするもの

123
1.23
12.3
.123
123.
.

だだ、これだと小数点単独のものと空文字列にもマッチしてしまう事が問題です。

余計なものは、手作業やプログラムで取り去ってしまうというのも1つの方法です。

また、\b\d*\.?\d*\b^\d*\.?\d*$ としても問題ないようでしたら実用には耐えられそうです。

ですが、やはり使い勝手が悪いので他のも考えてみます。

\d+\.?\d* にしてみました。

//マッチするもの

123
1.23
12.3
123.

小数点の後の0を省略したものが、マッチ出来るようになりました。

しかし、小数点の前の0を省略したものとはマッチしません。

そこで \d*\.?\d+ も試してみます。

//マッチするもの

123
1.23
12.3
.123

小数点の前の0を省略したものが、マッチ出来るようになりました。

かわりに、小数点の後の0を省略したものが出来なくなりました。

1つずつでは、足りないので2つ合わせてみます。

単純に組み合わせて、\d+\.?\d*|\d*\.?\d+としてみます。

//マッチするもの

123
1.23
12.3
123.
.123

目的のものが、マッチするようになりました。

しかし、効率も良くない(はず)の上に、美しくない正規表現です。

四苦八苦して改良したところ、筆者の能力では作れるものの中では、\d+\.?\d*|\.\d+ が一番効率が良いようです。

もう少し綺麗な記述をしたいところですが、上にあげたものを使い分ければ事足りることでしょう。


指数表記


  • [eE][+-]?\d+

  • \*10\^[+-]?\d+

  • [eE][+-]?\d+|\*10\^[+-]?\d+

  • [+-]?\d+(?:\.\d+)?(?:[eE][+-]?\d+)?

  • [+-]?\d+(?:\.\d+)?(?:\*10\^[+-]?\d+)?

  • [+-]?\d+(?:\.\d+)?(?:(?:[eE][+-]?\d+)|(?:\*10\^[+-]?\d+))?

  • [+-]?(?:\d+\.?\d*|\.\d+)(?:[eE][+-]?\d+)?

  • [+-]?(?:\d+\.?\d*|\.\d+)(?:\*10\^[+-]?\d+)?

  • [+-]?(?:\d+\.?\d*|\.\d+)(?:(?:[eE][+-]?\d+)|(?:\*10\^[+-]?\d+))?

指数表記には、10の累乗を使ったものとe(E)を使ったものがあります。

まずは、eを使った表記を考えます。

指数表記は、単純に実数の後にe1なとが付いたものになります。

そのため実数とマッチする正規表現に、eと指数部にマッチする正規表現を付ければ良いようです。

eと指数部にマッチするものは、[eE][+-]?\d+ です。

上で求めた実数の正規表現と組み合わせると、[+-]?\d+(?:\.\d+)?[eE][+-]?\d+ が指数表記の正規表現になります。

これだと指数表記のみとのマッチになります。

//マッチするもの

123e1
123e-1
1.23e1
1.23e+1

実数もマッチさせたい場合は、 [+-]?\d+(?:\.\d+)?(?:[eE][+-]?\d+)? で良いでしょう。

//マッチするもの

123
1.23
12.3
123e1
123E-1
1.23E1
1.23e+1

上記のものは、0の省略を許さないものです。

ここでも0の省略を許すと、[+-]?(?:\d+\.?\d*|\.\d+)(?:[eE][+-]?\d+)? となります。

//マッチするもの

123
1.23
12.3
.123
123.
123e1
123E-1
1.23E1
1.23e+1
.123e-1
123.e1

次に、10の累乗を使った表記を考えます。

10の累乗を使った表記を表す良い方法を知らないので、仮に *10^5 のように表すとします。

そうすると指数部にマッチする正規表現は、 \*10\^[+-]?\d+ となります。

これと実数を表す正規表現を組み合わせると、 [+-]?\d+(?:\.\d+)?(?:\*10\^[+-]?\d+)? あたりがもう一つの指数表記用の正規表現でしょう。

指数部を10累乗表記とe表記どちらにも対応させる事を考えます。

単純に組み合わせると、 [eE][+-]?\d+|\*10\^[+-]?\d+ になります。

((?:[eE]|(?:\*10\^))[+-]?\d+ とも表記できますが、単純にこの部分だけを考えた場合は、効率が悪くなるようです。)

これに実数部分を組み合わせると、[+-]?\d+(?:\.\d+)?(?:(?:[eE][+-]?\d+)|(?:\*10\^[+-]?\d+))? が両対応の正規表現です。

例によって0省略を許す場合は、[+-]?(?:\d+\.?\d*|\.\d+)(?:(?:[eE][+-]?\d+)|(?:\*10\^[+-]?\d+))? となります。


最後に

長々と書いた割には、いまいちな記事になってしまいました。

もっと良い記述があれば教えてもらいたいです。