6

次のような時間リテラルを含むpyLR1を使用して、カスタム記述言語のレクサールールを作成しています。

10h30m     # meaning 10 hours + 30 minutes
5m30s      # meaning 5 minutes + 30 seconds
10h20m15s  # meaning 10 hours + 20 minutes + 15 seconds
15.6s      # meaning 15.6 seconds

時・分・秒の指定順は、、、、固定hmするs。これを詳細に指定するには、次の有効な組み合わせが必要ですhmshmhmsmおよびs(もちろん、異なるセグメント間には数字が入ります)。おまけとして、正規表現はセグメント内の 10 進数 (つまり、非自然数) をチェックし、重要度が最も低いセグメントでのみこれらを許可する必要があります。

したがって、最後のグループを除くすべてのグループに対して、次のような数字の一致があります。

([0-9]+)

そして、最後のグループについても:

([0-9]*\.[0-9]+|[0-9]+(\.[0-9]*)?)  # to allow for .5 and 0.5 and 5.0 and 5

h、m、sa のすべての組み合わせを調べると、かわいい小さな python スクリプトで次の正規表現が得られます。

(([0-9]*\.[0-9]+|[0-9]+(\.[0-9]*)?)h|([0-9]+)h([0-9]*\.[0-9]+|[0-9]+(\.[0-9]*)?)m|([0-9]+)h([0-9]+)m([0-9]*\.[0-9]+|[0-9]+(\.[0-9]*)?)s|([0-9]*\.[0-9]+|[0-9]+(\.[0-9]*)?)m|([0-9]+)m([0-9]*\.[0-9]+|[0-9]+(\.[0-9]*)?)s|([0-9]*\.[0-9]+|[0-9]+(\.[0-9]*)?)s) 

明らかに、これはちょっとしたホラー表現です。これを簡単にする方法はありますか?回答は pythons モジュールで機能する必要があり、正規表現のサブセットが制限されているためにre機能しない回答も受け入れます。pyLR1

4

5 に答える 5

3

h, m,という表記を使用して、正規表現を素因数分解できます。s最も基本的なバージョンは次のとおりです。

h|hm|hms|ms|m|s

これはあなたが現在持っているものです。これを次のように分割できます。

(h|hm|hms)|(ms|m)|s

h次に、最初の式と 2 番目の式から引き出しmます ( (x|)==を使用x?):

h(m|ms)?|ms?|s

続けて、

h(ms?)?|ms?|s

これはおそらくより単純です (そしておそらく最も単純です)。


d小数を表す正規表現を追加すると ( のように\.[0-9]+)、これは次のように記述できます。

h(d|m(d|sd?)?)?|m(d|sd?)?|sd?

(つまり、各段階で、オプションで小数、または次への継続のいずれかを持ちますh mまたはs。)

これは次のような結果になります (時間と分だけ):

[0-9]+((\.[0-9]+)?h|h[0-9]+(\.[0-9]+)?m)|[0-9]+(\.[0-9]+)?m

これを見ると、pyLR1 に適した形式にすることはできない可能性があるため、すべての場所で小数を使用して解析を行い、次に二次チェックを行うことがこれを行うための最良の方法である可能性があります。

于 2012-07-02T12:07:08.017 に答える
1

以下の表現は理解できるはずです。使用している正確な正規表現構文がわからないため、有効な構文に自分で「変換」する必要があります。

あなたの時間

 [0-9]{1,2}h

あなたの議事録

[0-9]{1,2}m

あなたの秒

[0-9]{1,2}(\.[0-9]{1,3})?s

それらすべてを順番に並べて、それらのいずれかを省略できるようにしたい (でラップ?)

([0-9]{1,2}h)?([0-9]{1,2}m)?([0-9]{1,2}(\.[0-9]{1,3})?s)?

ただし、これは次のようなものと一致します:10h30s
有効な組み合わせはhmshmhshms、 または iow です。分は省略できますが、時間と秒は引き続き使用できますms

もう1つの問題は、空の文字列が指定された場合、3つすべてが有効になるため、一致?することです。したがって、何らかの方法でこれを回避する必要があります。うーん


@dbaapph(ms?)?|ms?|sを見ると、上記と一致することができます:

h: [0-9]{1,2}h
m: [0-9]{1,2}m
s: [0-9]{1,2}(\.[0-9]{1,3})?s

だからあなたは得る:

h(ms?)?: ([0-9]{1,2}h([0-9]{1,2}m([0-9]{1,2}(\.[0-9]{1,3})?s)?)?
  ms?  :              [0-9]{1,2}m([0-9]{1,2}(\.[0-9]{1,3})?s)?
   s   :                          [0-9]{1,2}(\.[0-9]{1,3})?s

これらすべてを一緒に OR すると、大きくても簡単に分解できる正規表現が得られます。

([0-9]{1,2}h([0-9]{1,2}m([0-9]{1,2}(\.[0-9]{1,3})?s)?)?|[0-9]{1,2}m([0-9]{1,2}(\.[0-9]{1,3})?s)?|[0-9]{1,2}(\.[0-9]{1,3})?s

これにより、空の文字列の問題の一致の両方を回避できますhs


@dbaappの回答に対する@Donal Fellowsのコメントを見て、私もやります(h?m)?S|h?M|H

(h?m)?s: (([0-9]{1,2}h)?[0-9]{1,2}m)?[0-9]{1,2}(\.[0-9]{1,3})?s
 h?m   :  ([0-9]{1,2}h)?[0-9]{1,2}m
 h     :   [0-9]{1,2}h

一緒にマージすると、上記よりも小さいものになります。

(([0-9]{1,2}h)?[0-9]{1,2}m)?[0-9]{1,2}(\.[0-9]{1,3})?s|([0-9]{1,2}h)?[0-9]{1,2}m|[0-9]{1,2}h

.xx次に、小数表現を一致させる方法を見つける必要があります

于 2012-07-02T12:14:29.563 に答える
1

動作する短い Python 式を次に示します。

(\d+h)?(\d+m)?(\d*\.\d+|\d+(\.\d*)?)(?(2)s|(?(1)m|[hms]))

条件に基づくCameron Martinsの回答に触発されました。

説明:

(\d+h)?                 # optional int "h" (capture 1)
(\d+m)?                 # optional int "m" (capture 2)
(\d*\.\d+|\d+(\.\d*)?)  # int or decimal 
(?(2)                   # if "m" (capture 2) was matched:
  s                       # "s"
| (?(1)                 # else if "h" (capture 1) was matched:
  m                       # "m"
|                       # else (nothing matched):
  [hms]))                 # any of the "h", "m" or "s"
于 2012-07-02T12:50:46.397 に答える
0

時間、分、秒がある場合があります。

    /(\d{1,2}h)*(\d{1,2}m)*(\d{1,2}(\.\d+)*s)*/

仕事をするべきです。正規表現ライブラリに応じて、アイテムを順番に取得するか、さらに解析して h、m、または s をチェックする必要があります。

この後者の場合、によって返されるものも参照してください。

   /(\d{1,2}(h))*(\d{1,2}(m))*(\d{1,2}(\.\d+)*(s))*/
于 2012-07-02T11:59:08.340 に答える
0

最後のグループは次のようになります。

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

合わせたくないなら5.


次のように正規表現 ifsを使用できます。

(([0-9]+h)?([0-9]+m)?([0-9]+s)?)(?(?<=h)(([0-9]*\.[0-9]+|[0-9]+(\.[0-9]*)?)m)?|(?(?<=m)(([0-9]*\.[0-9]+|[0-9]+(\.[0-9]*)?)s)?|\b(([0-9]*\.[0-9]+|[0-9]+(\.[0-9]*)?)[hms])?))

ここ - http://regexr.com?31dmj

これが機能することを確認していませんが、最初に時間、分、次に秒の整数のみを照合しようとします。次に、最後に一致したものが時間の場合は分数を許可し、最後に一致したものが分である場合は許可します小数秒。

于 2012-07-02T12:10:37.057 に答える