Hiroshi Araki
Hiroshi Araki

Reputation: 65

Easy/Simple way to write switch-like regular expressions

I'm newbie for Python and wondering what is best way to write a code below in perl into python:

if ($line =~ /(\d)/) {
   $a = $1
}
elsif ($line =~ /(\d\d)/) {
   $b = $1
}
elsif ($line =~ /(\d\d\d)/) {
   $c = $1
}

What I want to do is to retrieve a specific part of each line within a large set of lines. In python all what I can do is as below and is very ugly.

res = re.search(r'(\d)', line)
if res:
  a = res.group(1)
else:
  res = re.search(r'(\d\d)', line)
  if res:
    b = res.group(1)
  else:
    res = re.search(r'(\d\d\d)', line)
    if res:
      c = res.group(1)

Does any one know better way to write same thing without non-built-in module?

EDIT:

How do you write if you need parse line using very different re? My point here is it should be simple so that any one can understand what the code is doing there. In perl, we can write:

if ($line =~ /^this is a sample line (.+) and contain single value$/) {
  $name = $1
}
elsif ($line =~ /^this is another sample: (.+):(.+) two values here$/) {
  ($address, $call) = ($1, $2)
}
elsif ($line =~ /^ahhhh thiiiss isiss (\d+) last sample line$/) {
  $description = $1
}

From my view, this kind perl code is very simple and easy to understand.

EDIT2: I found same discussion here:

http://bytes.com/topic/python/answers/750203-checking-string-against-multiple-patterns

So there's no way to write in python simple enough like perl..

Upvotes: 1

Views: 118

Answers (3)

Eric
Eric

Reputation: 97575

You could write yourself a helper function to store the result of the match at an outer scope so that you don't need to rematch the regex in the if statement

def search(patt, str): 
    search.result = re.search(patt, str)
    return search.result

if search(r'(\d)', line):
    a = search.result.group(1)
elif search(r'(\d\d)', line):
    b = search.result.group(1)
elif search(r'(\d\d\d)', line):
    c = search.result.group(1)

In python 3.8, you'll be able to use:

if res := re.search(r'(\d)', line):
    a = res.group(1)
elif res := re.search(r'(\d\d)', line):
    b = res.group(1)
elif res := re.search(r'(\d\d\d)', line):
    c = res.group(1)

Upvotes: 2

Craig Burgler
Craig Burgler

Reputation: 1779

Similar to perl except 'elif' instead of 'elsif' and ':' after the test and no curly braces (replaced by indentation) and optional parenthesis. There are many resources on the web which describe Python statements and more which can be easily found with a google search.

if re.search(r'(\d)', line):
    a = re.search(r'(\d)', line).group(1)
elif re.search(r'(\d\d)', line):
    b = re.search(r'(\d\d)', line).group(1)
elif re.search(r'(\d\d\d)', line):
    c = re.search(r'(\d\d\d)', line).group(1)

Of course the logic of the code is flawed since 'b' and 'c' never get set but I think this is the syntax you were looking for.

Upvotes: 0

Avinash Raj
Avinash Raj

Reputation: 174696

Order of the pattern is very important. Because if you use this (\d)|(\d\d)|(\d\d\d) pattern, the first group alone will match all the digit characters. So, it won't try to check the next two patterns, since the first pattern alone will find all the matches.

res = re.search(r'(\d\d\d)|(\d\d)|(\d)', line)
if res:
    a, b, c = res.group(3), res.group(2), res.group(1)

DEMO

Upvotes: 2

Related Questions