【问题标题】:Python: Regex Function Parsing Through Email String and Returning Tuple Or Returning ValueError If Input InvalidPython:通过电子邮件字符串解析正则表达式函数并返回元组或如果输入无效则返回 ValueError
【发布时间】:2021-05-22 16:16:20
【问题描述】:

我想编写一个函数来解析电子邮件输入并返回一个带有 (id, domain) 的元组。 id 是用户名,而 domain 是域名。以@字符分隔的电子邮件

例如:kyle@asu.edu 将解析为 ('kyle', 'asu.edu')。但以下是对该功能的一些额外限制:

  • 用户名以字母字符开头
  • 域名以字母字符结尾
  • 允许使用特殊字符,例如 .、-、_ 或 +
  • 不允许使用空格字符,包括前导或尾随空格

因此,如果违反上述任何规则,则电子邮件输入不会被视为有效的电子邮件地址,应引发 ValueError。

以下是我尝试的代码,但不太有效:

def email_func(string_input):
    """Parses a string as an email address, returning an (id, domain) pair."""
    ###
    ### YOUR CODE HERE
    regex_parse = re.search(r'([a-zA-Z_+-.]+)@([a-zA-Z.-]+)', string_input) 
    # print (regex_parse)
    
    try:
        return regex_parse.groups()
    
    except ValueError:
        raise ValueError ('not a valid email address')
    ###

举个简单的例子。

email_func('kyle@asu.edu') returns `('kyle', 'asu.edu')` which is correct.  

我的代码不起作用的实例:

  1. 对于带有空格的无效输入字符串,我不会引发 ValueError。例如: email_func('kyle @asu.edu') 输出错误:

    ---> 11 返回 regex_parse.groups()
    AttributeError:“NoneType”对象没有属性“组”

  2. 我没有收到前导空格的 ValueError:例如:email_func(' kyle@asu.edu') 输出 ('kyle', 'asu.edu') 与尾随空格相同的问题。

  3. 如何在我的正则表达式中指定电子邮件不能以数字开头或结尾/必须是字母字符?

【问题讨论】:

  • 你为什么期待ValueError?当re.search() 找不到匹配项时,它返回NoneNone.groups() 提升 AttributeError,而不是 ValueError
  • 嗯,我没有意识到这一点。我将研究这两个错误之间的区别。

标签: python regex match valueerror


【解决方案1】:
  1. 如您所见,当regex_parseNone 时,调用regex_parse.groups() 会引发AttributeError,而不是ValueError,这是re.search() 找不到匹配项时返回的内容。所以将except ValueError: 更改为except AttributeError:。或者你可以简单地使用
if regex_parse is None: 
    raise ValueError("Not a valid email address")
  1. 您应该锚定您的正则表达式,使其必须匹配整个字符串,而不是在字符串中的任何位置搜索匹配项。 r'^([a-zA-Z_+-.]+)@([a-zA-Z.-]+)$'^ 匹配开头,$ 匹配结尾。
  2. [a-zA-Z] 开始和结束正则表达式。
    r'([a-zA-Z][a-zA-Z_+-.]*)@([a-zA-Z.-]*[a-zA-Z])'

【讨论】:

  • 成功了!谢谢 :) 你有推荐的网站来练习正则表达式问题吗?
  • regex101.com 很好。它显示正则表达式各部分含义的细分。
【解决方案2】:

我假设您输入的只是一个电子邮件地址,您需要对其进行验证。所以没有必要使用search。您真正需要的是 match 函数。

对您的代码稍作改动后,它看起来像这样:

def email_func(string_input):
    """Parses a string as an email address, returning an (id, domain) pair."""
    ###
    ### YOUR CODE HERE
    regex_parse = re.match(r'([a-zA-Z_+-.]+)@([a-zA-Z.-]+)', string_input) 
    # print (regex_parse)
    
    if regex_parse:
        return regex_parse.groups()
    
    else:
        raise ValueError ('not a valid email address')
    ###

【讨论】:

  • 啊,是的……你能解释一下什么时候在概念上使用搜索和匹配比较合适吗?
  • this answer中解释得更好。
  • 一般来说,“search”函数在整个字符串中搜索匹配模式的子字符串,就像Ctrl+F,而“match”函数一次检查整个字符串,看是否匹配给定的模式。
【解决方案3】:

下面应该返回一个元组(用户名,域)。如果您的任何约束被违反,它将引发 except 块。根据需要进行修改。

def email_func(string_input):

    username_template = r'^[a-z][a-z\d_\.+=-]{0,30}@'
    domain_template = r'@\w*\.[a-z]+'

    try:
        username = re.search(username_template, string_input)
        domain = re.search(domain_template, string_input)

        email_tuple = (username.group(0).strip('@'), domain.group(0).strip('@'))

        return email_tuple

    except AttributeError:
        print('please enter a valid email.')

为了获取用户名,下面的正则表达式会检查以确保它以拉丁字母 ^[a-z] 开头,然后是用户名的其余部分。如果 ^[a-z] 被违反,就会触发 except 块。

username_template = r'^[a-z][a-z\d_\.=-]{0,30}@'

为了捕获域,下面的正则表达式会检查以确保一切都在 .是拉丁字母而不是数字:.[a-z]+

domain_template = r'@\w*\.[a-z]+'

【讨论】:

    猜你喜欢
    • 2011-09-09
    • 2018-07-23
    • 2018-11-08
    • 2012-02-19
    • 1970-01-01
    • 1970-01-01
    • 2011-07-01
    • 1970-01-01
    • 2011-10-17
    相关资源
    最近更新 更多