1

以下の正規表現マッチングで何が間違っているのですか

>>> import re
>>> d="30-12-2001"
>>> re.findall(r"\b[1-31][/-:][1-12][/-:][1981-2011]\b",d)
[]
4

6 に答える 6

6

[1-31] matches 1-3 and 1 which is basically 1, 2 or 3. You cannot match a number rage unless it's a subset of 0-9. Same applies to [1981-2011] which matches exactly one character that is 0, 1, 2, 8 or 9.

The best solution is simply matching any number and then checking the numbers later using python itself. A date such as 31-02-2012 would not make any sense - and making your regex check that would be hard. Making it also handle leap years properly would make it even harder or impossible. Here's a regex matching anything that looks like a dd-mm-yyyy date: \b\d{1,2}[-/:]\d{1,2}[-/:]\d{4}\b

However, I would highly suggest not allowing any of -, : and / as : is usually used for times, / usually for the US way of writing a date (mm/dd/yyyy) and - for the ISO way (yyyy-mm-dd). The EU dd.mm.yyyy syntax is not handled at all.

If the string does not contain anything but the date, you don't need a regex at all - use strptime() instead.

All in all, tell the user what date format you expect and parse that one, rejecting anything else. Otherwise you'll get ambiguous cases such as 04/05/2012 (is it april 5th or may 4th?).

于 2012-04-10T10:26:50.340 に答える
1

[1-31]あなたが思っていることを意味するわけではありません。角かっこの構文は、数字の範囲ではなく、文字の範囲に一致します。数値の範囲を正規表現で照合することは可能ですが、扱いにくいです。

(日付解析ライブラリではなく)これに正規表現を本当に使用したい場合は、正しい桁数のすべての数字を照合し、値をキャプチャしてから、自分で値を確認することをお勧めします。

>>> import re
>>> d="30-12-2001"
>>> >>> re.findall(r"\b([0-9]{1,2})[-/:]([0-9]{1,2})[-/:]([0-9]{4})\b",d)
[('30', '12', '2001')]

のような無効な日付をキャッチするには、とにかく実際の日付の検証を行う必要があります31-02-2012

[/-:](範囲として解釈されるため、どちらも機能しないことに注意してください。[-/:]代わりに使用してください。ハイフンを前に置くと、範囲区切りとして解釈されなくなります。)

于 2012-04-10T10:31:09.870 に答える
1

あなたはおそらくそれを間違っています。ここでの他のいくつかの返信は正規表現であなたを助けていますが、datetime.strptimeメソッドを使用してフォーマットされた日付を日時オブジェクトに変換し、そのオブジェクトでさらにロジックを実行することをお勧めします:

>>> import datetime
>>> datetime.strptime('30-12-2001', '%d-%m-%Y')
datetime.datetime(2001, 12, 30, 0, 0)

strptime メソッドとそのフォーマット文字列の詳細。

于 2012-04-10T10:35:01.713 に答える
1

正規表現は数値を認識しません。正規表現で1は、文字列の単なる文字です - 同じ種類のものaです。したがって、たとえば、は範囲と (冗長な) 単一の記号[1-31]を含む文字クラスとして解析されます。1-31

日付の解析に正規表現を使用したくない場合。日付の解析を処理するための組み込みモジュールが既にあります。

>>> import datetime
>>> datetime.datetime.strptime('30-12-2001', '%d-%m-%Y')
datetime.datetime(2001, 12, 30, 0, 0) # an object representing the date.

これは、すべての二次チェック (2 月 31 日の参照の試行など) も行います。複数の種類の区切り記号を処理する場合は、元の文字列で単純.replaceにそれらをすべて同じ区切り記号に変換し、それを形式で使用できます。

于 2012-04-10T10:33:00.880 に答える
1

regexp = r'(0?[1-9]|[12][0-9]|3[01])/(0?[1-9]|1[012])/((19|20)\ d\d)'

( #グループ #1 の開始
 0?[1-9] # 01-09 または 1-9
 | | # ..また
 [12][0-9] # 10-19 または 20-29
 | | # ..また
 3[01] #30、31
) #グループの終わり #1
  / # "/" が続く
   ( # グループ #2 の開始
    0?[1-9] # 01-09 または 1-9
    | | # ..また
    1[012] #10,11,12
    ) # グループの終わり #2
     / # "/" が続く
      ( # グループ #3 の開始
       (19|20)\\d\\d # 19[0-9][0-9] または 20[0-9][0-9]
       ) # グループの終わり #3
于 2012-06-30T19:41:37.420 に答える