2

期間を表す文字列の内容を解析する必要があります。文字列の形式は、値/単位です (例: 1s、60min、24h)。実際の値 (int) と単位 (str) を別々の変数に分けます。

現時点では、次のようにしています。

def validate_time(time):
    binsize = time.strip()
    unit = re.sub('[0-9]','',binsize)
    if unit not in ['s','m','min','h','l']:
        print "Error: unit {0} is not valid".format(unit)
        sys.exit(2)
    tmp = re.sub('[^0-9]','',binsize)
    try:
        value = int(tmp)
    except ValueError:
        print "Error: {0} is not valid".format(time) 
        sys.exit(2)
    return value,unit

ただし、1m0 のようなものも (誤って) 検証されるため、理想的ではありません ( value=10unit=m)。

この入力を検証/解析する最良の方法は何ですか?

4

3 に答える 3

2

1 つの正規表現で行全体を解析するだけです。

_timeunit = re.compile(r'^(?P<value>\d+)(?P<unit>s|m|min|h|l)$')
def validate_time(time):
    match = _timeunit.match(time.strip())
    if match is None:
        print "Error: {0} is not valid".format(time)
        sys.exit(2)

    return int(match.group('value')), match.group('unit')

デモ (sys.exit を一時的に return に置き換えたもの):

>>> validate_time('10l')
(10, 'l')
>>> validate_time('10l0')
Error: 10l0 is not valid

^正規表現は、最初の数字 (キャレットで一致) に一致し、次にsmminhまたはの限られたセットの単位に一致しますlが、それらが行末にある場合のみ、$ドル記号に一致します。

ところで、検証メソッドで例外を発生させ、メソッドを呼び出している場所でその例外を処理するのは、よりPythonicです。これにより、より再利用可能になります。

_timeunit = re.compile(r'^(?P<value>\d+)(?P<unit>s|m|min|h|l)$')
def validate_time(time):
    match = _timeunit.match(time.strip())
    if match is None:
        raise ValueError('{0} is not a valid timespan'.format(time))    
    return int(match.group('value')), match.group('unit')

try:
    validate_time(foobar)
except ValueError, e:
    print 'Error: {0}'.format(e.args[0])
    sys.exit(2)
于 2012-09-06T16:15:28.127 に答える
0

一度に解析してみませんか:

m = re.match(r'(?P<value>\d+)\s*(?P<unit>\w+)',time.strip())
#              #^number
#                            #^spaces (optional) 
#                               #^non-number
if not m:
   pass #error

if m.group(0) != time.strip():
   pass #error -- leftover stuff at the end.  This will catch '1m0'

unit = m.group('unit')
value = int(m.group('value'))
于 2012-09-06T15:36:00.503 に答える
0

これを試してください:

#!/usr/bin/env python

import re

time = '1m'
try:
  m = re.match(r'^(?P<value>\d+)(?P<middle>.*)(?P<unit>(m|min|s|h|l))$',
    time.strip())
  value = m.group('value')
  unit = m.group('unit')
  middle = m.group('middle')
  if middle :
    # Reuse the exception raised if an expected group is not found
    raise AttributeError
  print value, unit
except AttributeError:
  print "Wrong format"

時刻が数字で始まり、有効な単位で終わり、途中で何かがキャッチされるようにします。

于 2012-09-06T16:10:41.353 に答える