How do you translate this regular-expression idiom from Perl into Python?

后端 未结 15 616
情深已故
情深已故 2020-12-04 11:16

I switched from Perl to Python about a year ago and haven\'t looked back. There is only one idiom that I\'ve ever found I can do more easily in Perl than in Python:<

相关标签:
15条回答
  • 2020-12-04 11:41

    I'd suggest this, as it uses the least regex to accomplish your goal. It is still functional code, but no worse then your old Perl.

    import re
    var = "barbazfoo"
    
    m = re.search(r'(foo|bar|baz)(.+)', var)
    if m.group(1) == 'foo':
        print m.group(1)
        # do something with m.group(1)
    elif m.group(1) == "bar":
        print m.group(1)
        # do something with m.group(1)
    elif m.group(1) == "baz":
        print m.group(2)
        # do something with m.group(2)
    
    0 讨论(0)
  • 2020-12-04 11:42

    Starting Python 3.8, and the introduction of assignment expressions (PEP 572) (:= operator), we can now capture the condition value re.search(pattern, text) in a variable match in order to both check if it's not None and then re-use it within the body of the condition:

    if match := re.search(r'foo(.+)', text):
      # do something with match.group(1)
    elif match := re.search(r'bar(.+)', text):
      # do something with match.group(1)
    elif match := re.search(r'baz(.+)', text)
      # do something with match.group(1)
    
    0 讨论(0)
  • 2020-12-04 11:44
    import re
    
    s = '1.23 Million equals to 1230000'
    
    s = re.sub("([\d.]+)(\s*)Million", lambda m: str(round(float(m.groups()[0]) * 1000_000))+m.groups()[1], s)
    
    print(s)
    

    1230000 equals to 1230000

    0 讨论(0)
  • 2020-12-04 11:46

    Using named groups and a dispatch table:

    r = re.compile(r'(?P<cmd>foo|bar|baz)(?P<data>.+)')
    
    def do_foo(data):
        ...
    
    def do_bar(data):
        ...
    
    def do_baz(data):
        ...
    
    dispatch = {
        'foo': do_foo,
        'bar': do_bar,
        'baz': do_baz,
    }
    
    
    m = r.match(var)
    if m:
        dispatch[m.group('cmd')](m.group('data'))
    

    With a little bit of introspection you can auto-generate the regexp and the dispatch table.

    0 讨论(0)
  • 2020-12-04 11:48

    Here's the way I solved this issue:

    matched = False;
    
    m = re.match("regex1");
    if not matched and m:
        #do something
        matched = True;
    
    m = re.match("regex2");
    if not matched and m:
        #do something else
        matched = True;
    
    m = re.match("regex3");
    if not matched and m:
        #do yet something else
        matched = True;
    

    Not nearly as clean as the original pattern. However, it is simple, straightforward and doesn't require extra modules or that you change the original regexs.

    0 讨论(0)
  • 2020-12-04 11:48

    Expanding on the solution by Pat Notz a bit, I found it even the more elegant to:
      - name the methods the same as re provides (e.g. search() vs. check()) and
      - implement the necessary methods like group() on the holder object itself:

    class Re(object):
        def __init__(self):
            self.result = None
    
        def search(self, pattern, text):
            self.result = re.search(pattern, text)
            return self.result
    
        def group(self, index):
            return self.result.group(index)
    

    Example

    Instead of e.g. this:

    m = re.search(r'set ([^ ]+) to ([^ ]+)', line)
    if m:
        vars[m.group(1)] = m.group(2)
    else:
        m = re.search(r'print ([^ ]+)', line)
        if m:
            print(vars[m.group(1)])
        else:
            m = re.search(r'add ([^ ]+) to ([^ ]+)', line)
            if m:
                vars[m.group(2)] += vars[m.group(1)]
    

    One does just this:

    m = Re()
    ...
    if m.search(r'set ([^ ]+) to ([^ ]+)', line):
        vars[m.group(1)] = m.group(2)
    elif m.search(r'print ([^ ]+)', line):
        print(vars[m.group(1)])
    elif m.search(r'add ([^ ]+) to ([^ ]+)', line):
        vars[m.group(2)] += vars[m.group(1)]
    

    Looks very natural in the end, does not need too many code changes when moving from Perl and avoids the problems with global state like some other solutions.

    0 讨论(0)
提交回复
热议问题