代码之家  ›  专栏  ›  技术社区  ›  killown

避免使用regex[python]

  •  2
  • killown  · 技术社区  · 16 年前

    我想知道这是不是一个好主意,避免regex。

    事实上,我在任何情况下都避免了它,有些人一直给我建议,我不应该避免它,因为如果你知道什么意味着每件事,比如:

    []''\a\b\d\d\w\w\s\z$*?…

    很容易看懂,对吧?但我觉得我想避免使用regex,我会有一个更可读的代码。

    当它变大时,它会变得更不可读,例如: validators.py

    email_re = re.compile(
        r"(^[-!#$%&'*+/=?^_`{}|~0-9A-Z]+(\.[-!#$%&'*+/=?^_`{}|~0-9A-Z]+)*"  # dot-atom
        r'|^"([\001-\010\013\014\016-\037!#-\[\]-\177]|\\[\001-011\013\014\016-\177])*"' #     quoted-string
        r')@(?:[A-Z0-9](?:[A-Z0-9-]{0,61}[A-Z0-9])?\.)+[A-Z]{2,6}\.?$', re.IGNORECASE)  # domain
    

    所以,我想知道一个不回避雷杰克斯的理由?

    6 回复  |  直到 11 年前
        1
  •  18
  •   paxdiablo    16 年前

    不,不要避免使用正则表达式。它们实际上是一个非常漂亮的小工具,如果你明智地使用它们,可以节省你很多工作。

    你什么 做 需要避免的是尝试将它用于所有事情,在正则表达式变得更温和和不那么倾心之前,这些新表达式似乎会遇到一种不适:—)

    例如, 不要 使用它来验证电子邮件地址。验证电子邮件地址的方法是向其发送一封电子邮件,其中包含一个链接,收件人必须单击该链接才能完成“事务”。

    有数以十亿计的有效电子邮件地址(根据RFC)背后没有物理电子邮件接收器。这个 只有 确定有接收者的方法是发送一封电子邮件,并等待其收到并采取行动的确凿证据。

    如果我发现自己在写一个超过60个字符的正则表达式,我会后退一步,看看是否有更可读的方法。同样地,如果我写了一个正则表达式,一周后又回来,并且不能立即识别它的作用,我会考虑替换它。这段话当然是由我的意见组成的,但它们对我很有帮助。

        2
  •  6
  •   Bryan Oakley    16 年前

    正则表达式是一种工具。它们非常适合某些任务,而不适合其他任务。像任何工具一样,当它们是适合工作的工具时,使用它们。不要仅仅因为有人说他们很坏就避开他们。学习如何使用它们,然后你可以自己决定,而不是依赖别人的教条。

        3
  •  2
  •   Alex Martelli    16 年前

    如果您选择使用更通用的分析方法,例如 pyparsing 或 PLY 你永远不会 要求 正则表达式(只能匹配与此类常规分析器匹配的语言的一小部分)。但是,像在 PLY 通常是围绕正则表达式构建的(这是满足lexer需求的完美匹配!),因此您可能必须避免这种情况(以及诸如 BeautifulSoup 当任何“普通”用户可以通过简单地将正则表达式对象作为选择器来继续使用和享受它时,因为 美人汤 完全支持这一点),并且必须用您选择的通用解析包重新编码许多这样的现有解析器。

    当然,如果在更简单、高度优化和简洁的工具是完美的解决方案的情况下使用非常通用的工具,那么性能可能会受到很大的影响——在许多常见的情况下,代码的大小可能会“放大”到非常大。但是如果你不介意让程序大一倍,慢一倍,并且决心不惜一切代价避免正则表达式,那么 可以 那样做。

    另一方面,如果您的主要关注点是可读性(也是一个可以理解和值得称赞的关注点),那么 re.VERBOSE 通过允许在re模式中大量使用空白和注释,选项确实可以在不删除的情况下为该目标创造奇迹。 任何 对Res的优点(通过稀释有时过于简洁的内容除外;-)。你会想的 也 当然,在您的腰带下至少要有一个通用的解析系统(而不是像许多人不幸做的那样,将res扩展到他们错误的任务上!)--但是,在很多情况下(包括,充分利用 美人汤 以及许多其他可以接受res作为参数来适当地应用它们的工具),我认为这是值得推荐的。

        4
  •  1
  •   Tony Veijalainen    16 年前

    只是为了比较一下,这里我的版本电子邮件格式检查没有与regexp(与测试案例)和一个可读的regexp提供给我作为替代(尽管在它被接受后发送电子邮件,是个好主意):

    # -*- coding: utf8 -*- 
    import string
    print("Valid letters in this computer are: "+string.letters)
    import re 
    def validateEmail(a): 
        sep=[x for x in a if not (x.isalpha() or 
                                  x.isdigit() or 
                                  x in r"!#$%&'*+-/=?^_`{|}~]") ] 
        sepjoined=''.join(sep) 
        ## sep joined must be ..@.... form 
        if len(a)>255 or sepjoined.strip('.') != '@': return False 
        end=a 
        for i in sep: 
            part,i,end=end.partition(i) 
            if len(part)<2: return False 
        return len(end)>1 
    
    def emailval(address): 
        pattern = "[\.\w]{2,}[@]\w+[.]\w+" 
        return re.match(pattern, address)
    
    if __name__ == '__main__': 
        emails = [ "test.@web.com","test+john@web.museum", "test+john@web.m", 
                   "a@n.dk", "and.bun@webben.de","marjaliisa.hämäläinen@hel.fi", 
                   "marja-liisa.hämäläinen@hel.fi", "marjaliisah@hel.",'tony@localhost',
                   '1234@23.45','me@somewhere'] 
    
        print('\n\t'.join(["Valid emails are:"] + 
                          filter(validateEmail,emails)))
    
        print('\n\t'.join(["Regexp gives wrong answer:"] + 
                           filter(emailval,emails)))
    
    """ Output:
    Valid letters in this computer are: abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ
    Valid emails are:
            test+john@web.museum
            and.bun@webben.de
            tony@localhost
            1234@23.45
            me@somewhere
    Regexp gives wrong answer:
            test.@web.com
            and.bun@webben.de
            1234@23.45
    """
    

    编辑:从这个古老的代码中清除了regex过滤器功能,为基于@detly link的更宽松版本编辑。很好,在发送确认邮件之前先为我检查一下表格。最后在注释中输入255个字符的长度限制检查。

    此代码不接受普通的a@b作为有效的电子邮件地址,但接受我@某处。另一件事是它取决于isalpha返回的内容。所以这个来自ideone.com的输出没有接受斯堪的纳维亚语,即使它们现在是有效的。在我的家庭计算机上运行时,这些都被接受。即使存在编码行,也是如此。

        5
  •  0
  •   kindall    16 年前

    (删除了一个据称是“官方”表达式的正则表达式,但事实上在其声称来自的RFC中找不到它。)

    This Regex可能很有趣,因为它试图精确匹配旧版本的Internet邮件标准中提供的电子邮件地址语法。

        6
  •  -1
  •   damzam    16 年前

    正则表达式可能是提取/验证电子邮件地址的正确工具…

    要从原始文本中提取一个或多个电子邮件地址:

    import re
    pat_e = re.compile(r'(?P<email>[\w.+-]+@(?:[\w-]+\.)+[a-zA-Z]{2,})')
    emails = []
    for r in pat_e.finditer(text):
      emails.append(r.group('email'))
    return emails
    

    要查看单个文本是否为有效电子邮件:

    import re
    pat_m = re.compile(r'([\w.+-]+@(?:[\w-]+\.)+[a-zA-Z]{2,}$)')
    if pat_m.match(text):
      return True
    return False