テキスト内のカンマや小数点の有無にかかわらず数字を一致させる正規表現 質問する

テキスト内のカンマや小数点の有無にかかわらず数字を一致させる正規表現 質問する

テキスト本文内のすべての数字を検索して置換しようとしています。いくつかの正規表現の例を見つけましたが、これでほぼ問題は解決しましたが、まだ完璧ではありません。問題は、テキスト内の数字に小数点やカンマが含まれているかどうかわからないことです。例:

「5000ポンドのキツネが99,999.99998713フィートのフェンスを飛び越えました。」

正規表現は「5000」と「99,999.99998713」を返す必要があります。私が見つけた例では、数字がコンマで分割されていたり、小数点以下 2 桁に制限されていました。一部の例が小数点以下 2 桁に制限されている理由がわかるくらい正規表現を理解し始めていますが、それを克服して、コンマを含めてシーケンス全体を取得する方法をまだ学んでいません。

これが私の最新バージョンです:

[0-9]+(\.[0-9][0-9]?)?

上記のテキストに対して、「5000」、「99,99」、「9.99」、および「 」が返されます。998713

ベストアンサー1

編集: この投稿は多くの閲覧数を獲得しているので、まずは皆さんが Google で検索した内容をお伝えします。

#ALL THESE REQUIRE THE WHOLE STRING TO BE A NUMBER
#For numbers embedded in sentences, see discussion below

#### NUMBERS AND DECIMALS ONLY ####
#No commas allowed
#Pass: (1000.0), (001), (.001)
#Fail: (1,000.0)
^\d*\.?\d+$

#No commas allowed
#Can't start with "."
#Pass: (0.01)
#Fail: (.01)
^(\d+\.)?\d+$

#### CURRENCY ####
#No commas allowed
#"$" optional
#Can't start with "."
#Either 0 or 2 decimal digits
#Pass: ($1000), (1.00), ($0.11)
#Fail: ($1.0), (1.), ($1.000), ($.11)
^\$?\d+(\.\d{2})?$

#### COMMA-GROUPED ####
#Commas required between powers of 1,000
#Can't start with "."
#Pass: (1,000,000), (0.001)
#Fail: (1000000), (1,00,00,00), (.001)
^\d{1,3}(,\d{3})*(\.\d+)?$

#Commas required
#Cannot be empty
#Pass: (1,000.100), (.001)
#Fail: (1000), ()
^(?=.)(\d{1,3}(,\d{3})*)?(\.\d+)?$

#Commas optional as long as they're consistent
#Can't start with "."
#Pass: (1,000,000), (1000000)
#Fail: (10000,000), (1,00,00)
^(\d+|\d{1,3}(,\d{3})*)(\.\d+)?$

#### LEADING AND TRAILING ZEROES ####
#No commas allowed
#Can't start with "."
#No leading zeroes in integer part
#Pass: (1.00), (0.00)
#Fail: (001)
^([1-9]\d*|0)(\.\d+)?$

#No commas allowed
#Can't start with "."
#No trailing zeroes in decimal part
#Pass: (1), (0.1)
#Fail: (1.00), (0.1000)
^\d+(\.\d*[1-9])?$

さて、それはさておき、以下の大部分は、正規表現を巧みに使おうとするとどれほど複雑になるか、そしてなぜ代替手段を探す必要があるかについての解説を目的としています。自己責任でお読みください。


これは非常に一般的なタスクですが、私がこれまでに見た回答はすべて、、、または など、数値形式と一致しない入力を受け入れます。数字が他のテキストに埋め込まれている場合でも、修正するのは簡単です。私の意見では、1,234.56 と 1234 を引き出せないものはすべて,1119,9,9.,,.そしてそれらの数字だけ—out of はabc22 1,234.56 9.9.9.9 def 1234不正解です。

まず、これをすべて 1 つの正規表現で行う必要がない場合は、行わないでください。2 つの異なる数値形式を 1 つの正規表現で管理するのは、他のテキストに埋め込まれていない場合でも困難です。実際に行うべきことは、全体を空白で分割し、結果に対して 2 つまたは 3 つの小さな正規表現を実行することです。それができない場合は、読み進めてください。

基本パターン

あなたが挙げた例を考慮すると、ほぼすべての整数または小数の0000形式を許可し、その他すべてをブロックする単純な正規表現は次のようになります。

^\d*\.?\d+$

フォーマットが必要なものは次のとおりです0,000

^\d{1,3}(,\d{3})*(\.\d+)?$

これらを組み合わせると、一貫性がある限り、カンマはオプションになります。

^(\d*\.?\d+|\d{1,3}(,\d{3})*(\.\d+)?)$

埋め込まれた数字

上記のパターンでは、入力全体が数字である必要があります。テキストに埋め込まれた数字を探しているので、その部分を緩める必要があります。一方で、catch2222 という数字を見つけて、それが見つかったと認識されることは望ましくありません。後読みをサポートするもの (C#、.NET 4.0+ など) を使用している場合、これは非常に簡単です。^を に置き換え(?<!\S)$を に置き換えるだけ(?!\S)で、準備完了です。

(?<!\S)(\d*\.?\d+|\d{1,3}(,\d{3})*(\.\d+)?)(?!\S)

JavaScript や Ruby などを使用している場合、状況はより複雑になってきます。

(?:^|\s)(\d*\.?\d+|\d{1,3}(?:,\d{3})*(?:\.\d+)?)(?!\S)

キャプチャ グループを使用する必要があります。後読みのサポートなしでは代替手段は考えられません。必要な数字はグループ 1 にあります (一致全体がグループ 0 であると仮定)。

検証とより複雑なルール

これであなたの質問は解決したと思いますので、必要なのはこれですべてであれば、ここで読むのをやめてください。もっと凝ったことをしたい場合、状況はすぐに非常に複雑になります。状況に応じて、以下のいずれかまたはすべてをブロックすることをお勧めします。

  • 入力内容が空です
  • 先頭のゼロ(例:000123)
  • 末尾のゼロ(例:1.2340000)
  • 小数点から始まる小数点数(例:0.001ではなく.001)

とりあえず、最初の 3 つをブロックして、最後の 1 つを許可したいとします。どうすればよいでしょうか。どうすればよいでしょうか。ルールごとに異なる正規表現を使用して、一致するものを徐々に絞り込む必要があります。ただし、チャレンジのために、すべてを 1 つの巨大なパターンで実行する方法は次のとおりです。

(?<!\S)(?=.)(0|([1-9](\d*|\d{0,2}(,\d{3})*)))?(\.\d*[1-9])?(?!\S)

これが意味するところは次の通りです:

(?<!\S) to (?!\S) #The whole match must be surrounded by either whitespace or line boundaries. So if you see something bogus like :;:9.:, ignore the 9.
(?=.)             #The whole thing can't be blank.

(                    #Rules for the integer part:
  0                  #1. The integer part could just be 0...
  |                  #
  [1-9]              #   ...otherwise, it can't have leading zeroes.
  (                  #
    \d*              #2. It could use no commas at all...
    |                #
    \d{0,2}(,\d{3})* #   ...or it could be comma-separated groups of 3 digits each.
  )                  # 
)?                   #3. Or there could be no integer part at all.

(       #Rules for the decimal part:
  \.    #1. It must start with a decimal point...
  \d*   #2. ...followed by a string of numeric digits only.
  [1-9] #3. It can't be just the decimal point, and it can't end in 0.
)?      #4. The whole decimal part is also optional. Remember, we checked at the beginning to make sure the whole thing wasn't blank.

ここでテスト済み:http://rextester.com/YPG96786

これにより、次のようなことが可能になります。

100,000
999.999
90.0009
1,000,023.999
0.111
.111
0

次のようなものがブロックされます:

1,1,1.111
000,001.111
999.
0.
111.110000
1.1.1.111
9.909,888

この正規表現をよりシンプルかつ短くする方法はいくつかありますが、パターンを変更すると数値とみなされる範囲が狭くなることに注意してください。

多くの正規表現エンジン (JavaScript や Ruby など) は否定の後読みをサポートしていないため、これを正しく行う唯一の方法はキャプチャ グループを使用することです。

(?:^|\s)(?=.)((?:0|(?:[1-9](?:\d*|\d{0,2}(?:,\d{3})*)))?(?:\.\d*[1-9])?)(?!\S)

探している番号はキャプチャ グループ 1 にあります。

ここでテスト済み:http://rubular.com/r/3HCSkndzhT

最後に

明らかに、これは巨大で複雑で、ほとんど読めない正規表現です。私はこの挑戦を楽しみました。これを本番環境で本当に使用するかどうかを検討してください。すべてを1ステップで実行するのではなく、2ステップで実行することもできます。かもしれない数字を一つ選び、さらにもう一つ選んでない数値。または、基本的な処理を実行してから、言語に組み込まれている数値解析関数を使用することもできます。選択はあなた次第です。

おすすめ記事