2009-09-09 4 views
7

だから私はこのようなエントリのうち、時間、分、秒を取得する必要があります:正規表現での時間/分/秒のマッチング - より良い方法ですか?

  • 4時43分12秒
  • 9.43.12
  • 1時
  • 01.04

最初の2つは時間、分、秒です。 次へは分と秒です。 最後の2つはほんの数秒です。

そして、私はそれが動作しますが、この正規表現を思い付いた..:

\A(?<hours>\d{1,2})(?::|\.)(?<minutes>\d{1,2})(?::|\.)(?<seconds>\d{1,2})\z|\A(?<minutes>\d{1,2})(?::|\.)(?<seconds>\d{1,2})\z|\A(?<seconds>\d{1,2})\z 

しかし、それは醜いです、と私は3種類の表情(主にちょうど学ぶため)ことがないようにそれをリファクタリングしたいと思います。

\A(?:(?<hours>\d{1,2})(?::|\.){0,1})(?:(?<minutes>\d{1,2})(?::|\.){0,1})(?:(?<seconds>\d{1,2}){0,1})\z 

しかし、それは動作しません - 分と秒は時々めちゃくちゃます:私はこれを試してみました。私の脳は痛いし、私は何が間違っているのか分かりません。

+1

これは言語に依存しません。正規表現の構文は、言語によって異なります。 –

答えて

10

私の提案:

構造
(?:(?:(?<hh>\d{1,2})[:.])?(?<mm>\d{1,2})[:.])?(?<ss>\d{1,2}) 

(?:      # group 1 (non-capturing) 
    (?:     # group 2 (non-capturing) 
    (?<hh>\d{1,2})  #  hours 
    [:.]    #  delimiter 
)?     # end group 2, make optional 
    (?<mm>\d{1,2})  # minutes 
    [:.]     # delimiter 
)?      # end group 1, make optional 
(?<ss>\d{1,2})   # seconds (required) 

ご希望の場合は、区切り文字で正規表現をラップすることができます - のようなワード境界\bまたは文字列のアンカー(^$)。

EDIT:それについて考えると、意味を成立させるだけの時間をキャプチャすることができます。 0と59のみ、適切な(秒と分)の間の値をキャプチャする

\d{1,2} 

の代わりに

[0-5]?\d 

を使用してください。

+0

regexpで構造化された例が大好きです... – gnarf

+0

恐ろしい!素晴らしい作品 - と書式も大好きです。私の編集者だけがそれをサポートすれば、それを扱う方が簡単です。 – Kjensen

+0

正規表現のコメント文字が「//無視」の代わりに「空白を無視してコメントを許可する」モードではありません。 – Joey

2

私は、次の式を示唆しています。

^(((?<Hour>[0-9]{1,2})[.:])?(?<Minute>[0-9]{1,2})[.:])?(?<Second>[0-9]{2})$

これは3:7:21のような一桁の分と合わせ一桁の時間をできるようになります。これが望ましくない場合は、若干の変更が必要です。第二の発現における

^(((?<Hour>[0-9]{1,2})[.:](?=[0-9]{2}))?(?<Minute>[0-9]{1,2})[.:])?(?<Second>[0-9]{2})$

肯定先読みアサーション(?=[0-9]{2})は、この問題を解決します。それは本当にすべての3つの部分が指定されていないときに何をするか、あなたの特定の状況に依存する

1

は、このためには実際に良い方法はありません。たとえば、多くの場合、3分30秒の代わりに3時間30分と解釈することをお勧めします。それについて明示的に傷つけることはできませんし、これらの入力の意味を正規表現から簡単に導き出すこともできます。

そこで私は個人的には最初の正規表現は全くその醜いではないと信じている - それはあまり「魔法」であるかもしれないが、それははるかに読みやすく、保守しています。あなたと他の人がコードを読み込んで変更できることを確認してください!

言語でサポートされている場合は、拡張正規表現(空白とコメントのサポート)を使用し、3行(または別の行にコメントを付ける場合は6または9)に分割します。それは正規表現を変更することはありませんが、それは確かに醜い感じが少なくなります。

+0

有効なポイント。私がそれをより良くしたい理由は、主に学ぶことです。 – Kjensen

5

私はまだこれをテストしていませんが、それが動作するはずです:

^(?:(?:(?<hours>\d\d?)[:\.])?(?<minutes>\d\d?)[:\.])?(?<seconds>\d\d?)$ 

は編集:
今、私はそれをテストし、それが動作することを確認しました。:)

+0

これは機能しますが、3:7:21をキャプチャして、3:07:21と予想される可能性があります。そして、文字グループでドットをエスケープする必要はありません。 (または間違っていますか?これを必要とする正規表現の実装はありますか?) –

+0

文字クラスのドットのバックスラッシュは不要です。 3時07分21秒に3:7:21を許可するのは、おそらく「受け入れるものに寛大である」という例です。 –

+0

私は厳密にエスケープする必要のない文字をエスケープする傾向があります。 Regexクラスがそれを理解する必要がない場合でも、私は可能性があります。 :) – Guffa

関連する問題