检测多个字符串之一的正则表达式

101

我有一个包含多个域名邮箱地址的列表。我需要一个正则表达式匹配属于三个特定域名的地址(在这个例子中为:foo,bar和baz)。

因此,以下地址将匹配:

  1. a@foo
  2. a@bar
  3. b@baz

以下地址不会匹配:

  1. a@fnord

理想情况下,以下地址也不会匹配(尽管这对于特定问题并不是至关重要):

  1. a@foobar
  2. b@foofoo

将问题抽象化一些:我想匹配包含给定子字符串列表中至少一个子串的字符串。

7个回答

198

使用管道符号 "|" 来表示 "或":

/a@(foo|bar|baz)\b/

如果你不想捕获分组,可以使用非捕获分组符号:

/a@(?:foo|bar|baz)\b/

当然,我假设在电子邮件地址前面使用“a”是可以的!您应该将其替换为适合的正则表达式。


这个程序缺少当前发布的数据,并且没有参考或解释。 - sfossen
7
我认为我没有漏掉任何东西。我的正则表达式与第一个列表匹配,但不匹配后面的两个列表,并且通常指示如何在正则表达式中进行“或”运算,这回答了最后一个问题。 - Jason Cohen
1
同意;我认为它解释得很好。 - Craig Walker
2
你刚刚帮我挽救了12-16根头发。我的头皮感谢您,先生! - Andy Hoffman

20
^(a|b)@(foo|bar|baz)$

如果您已经强制定义了一个列表,则开始和结束字符将仅搜索那三个字符串。


7

使用:

/@(foo|bar|baz)\.?$/i

请注意与其他答案的区别:
  • \.? - 匹配0或1个点,以防电子邮件地址中的域名是“完全限定”的
  • $ - 表示字符串必须以此序列结束,
  • /i - 使测试不区分大小写。
请注意,这假定每个电子邮件地址都在其自己的行上。
如果要匹配的字符串可以出现在字符串的任何位置,则删除$,并将其替换为\s+(它匹配一个或多个空格字符)。

我认为强制结束它有些过头了。 - sfossen
如果你不这样做,它就会匹配a@foosnoz。 - Alnitak
强制使用“。”是好的,但像a@foo这样的电子邮件地址必须像@foo.com.tw一样。 - sfossen
是的,当然可以(提示-我以DNS为生)。这些只是OP的示例域名。 - Alnitak
你的代码有一个错误——它会匹配"bar@foo"和"bar@foo.",但不会匹配"bar@foo.com"。我认为你的意思是"/@(foo|bar|baz)(?:.|$)/i"。 - Ben Blank
显示剩余2条评论

2
应该更通用,a不应计算在内,但@符号应该计算在内。
/@(foo|bar|baz)(?:\W|$)/

这里是有关正则表达式的良好参考资料。

编辑:更改结尾以允许模式结束或单词断点。现在假设foo/bar/baz是完整的域名。


实际上,'.' 结尾是可选的(这就是为什么我的后面跟着一个问号)。 - Alnitak
这是有争议的,直到他澄清foo === 'google.com'还是=== 'google'。 - sfossen
我将“foo”视为完整的域名,而不仅仅是一个前缀。 - Alnitak
可以使用更通用的 (?:\W|$)。 - sfossen

1

0

你不需要使用正则表达式来查找一个字符串是否包含给定列表中的至少一个子字符串。在Python中:

def contain(string_, substrings):
    return any(s in string_ for s in substrings)

以上方法对于大型字符串和多个子字符串的搜索速度较慢。GNU fgrep 可以高效地同时搜索多个模式。
使用正则表达式:
import re

def contain(string_, substrings):
    regex = '|'.join("(?:%s)" % re.escape(s) for s in substrings)
    return re.search(regex, string_) is not None

相关


不行,这样做不行。因为你会得到'a@foobar'和'b@foofoo'的误报。 - Andrew Harry
@Harry:你看了问题和我的回答吗?我的代码不是搜索域名,而是回答问题的第二部分:“我想匹配包含给定子字符串中至少一个的字符串。” - jfs

0

好的,我知道你要求一个正则表达式的答案。 但是你考虑过用'@'字符分割字符串, 取第二个数组值(域名) 并进行简单的匹配测试吗?

if (splitString[1] == "foo" && splitString[1] == "bar" && splitString[1] == "baz")
{
   //Do Something!
}

在我看来,正则表达式有点过头了。当然,我的假设是你的情况确实像你所列举的那样简单。


1
我需要正则表达式的原因是,我可以在不编写整个程序的情况下解析我的数据;我只需在30秒内将数据和正则表达式放入RegexBuddy中即可。 - Craig Walker
我的回答适用于你的问题,可能不适合你的特定情况,但stackoverflow的美妙之处在于它可能会帮助其他人。 - Andrew Harry

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接