1

I have the following code in shell:

case ${daterange} in
  *[Mm][Oo]*)
    factor=2592000
    ;;
  *[Ww]*)
    factor=604800
    ;;
  *[Dd]*)
    factor=86400
    ;;
  *[Hh]*)
    factor=3600
    ;;
  *)
    factor=60
    ;;
esac
num=`expr x"$TMFR" : x"[^0-9]*\([0-9]*\)"`
expr 0$num \* $factor

I wrote the following to convert it into python, but where I get stuck is the num= and expr lines. I dont know how to transfer them to python.

    if re.search(r'[Mm][Oo]', daterange):
        print "A"
    elif re.search(r'[Ww]', daterange):
        print "B"
    elif re.search(r'[Dd]', daterange):
        print "C"
    elif re.search(r'[Hh]', daterange):
        print "D"
    elif re.search(r'[Mm]', daterange):
        print "E"
    else:
        print "F"

daterange can contain values such as:

4h = which means 4 hours
4mo = which means 4 months
4w = which means 4 weeks
4d = which means 4 days
4m = which means 4 minutes
4s = which means 4 seconds

The goal here is to take the value in daterange and translate it into seconds.

5
  • 1
    re.search() seems overkill, as if 'mo' in daterange.lower(): would work too. Commented Jun 23, 2018 at 19:00
  • 1
    Have you checked out what expr does? Type man expr in your shell. You have a STRING : REGEXP test, so the matched text is stored in num. Commented Jun 23, 2018 at 19:01
  • 1
    The question really is: What value is $TMFR here? Commented Jun 23, 2018 at 19:04
  • Can these duration strings appear multiple times? Should they be combined when they do? So 1mo 2w 3d is 1 month, 2 weeks, and 3 days, totaling 4060800 seconds? Commented Jun 23, 2018 at 19:15
  • Should repeated patterns with no spaces in between be supported? Commented Jun 23, 2018 at 19:20

1 Answer 1

1

expr executes expressions:

  • expr x"$TMFR" : x"[^0-9]*\([0-9]*\)" matches the string x followed by the value of $TMFR against the regulare expression x[^0-9]*([0-9]*), printing out the part between the parentheses (which are escaped to prevent them from being interpreted by bash instead).
  • expr 0$num \* $factor multiplies the number $num by $factor, defaulting to 0.

So it basically finds the first numeric value in the string $TMFR and multiplies that number by the factor already calculated.

If you always have a number followed by a duration string, I'd just use a regular expression to extract both in one go, and use a dictionary to map the duration string to a factor:

import re

durations = {
    'mo': 2592000,
    'w': 604800,
    'd': 86400,
    'h': 3600,
    'm': 60,
    's': 1
}
# match on digits followed directly by one of the duration strings, ignoring case
# the duration strings are sorted by descending length to ensure shorter
# sub-patterns are considered after the longer options (compare 'mo' and m')
pattern = re.compile(r'(\d+)({})\b'.format(
    '|'.join(sorted(durations, key=len, reverse=True))),
    flags=re.IGNORECASE) 

def duration_from_string(s):
    return sum(
        int(m.group(1)) * durations[m.group(2)]
        for m in pattern.finditer(s))

I've assumed you need to support compound durations that are space separated, so 1mo 2w 3d is 4060800 seconds (1 month, 2 weeks and 3 days):

>>> duration_from_string('foo bar spam 1mo 2w 3d')
4060800

If the format should work without spaces too, drop the \b anchor from the regex pattern.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.