0

我有一个正则表达式来验证用户电子邮件地址。

/^(|(([A-Za-z0-9]+_+)|([A-Za-z0-9]+\-+)|([A-Za-z0-9]+\.+)|([A-Za-z0-9]+\++))*[A-Za-z0-9]+@((\w+\-+)|(\w+\.))*\w{1,63}\.[a-zA-Z]{2,})$/i"

在活动记录的帮助下,我想从数据库中获取电子邮件地址与此正则表达式不匹配的所有用户。我尝试了以下scope方法来达到预期的结果,但我得到的只是ActiveRecord::Relation.

scope :not_match_email_regex, :conditions => ["NOT email REGEXP ?'", /^(|(([A-Za-z0-9]+_+)|([A-Za-z0-9]+\-+)|([A-Za-z0-9]+\.+)|([A-Za-z0-9]+\++))*[A-Za-z0-9]+@((\w+\-+)|(\w+\.))*\w{1,63}\.[a-zA-Z]{2,})$/"]

这给了我以下查询:

SELECT `users`.* FROM `users` WHERE (email REGEXP '--- !ruby/regexp /^(|(([A-Za-z0-9]+_+)|([A-Za-z0-9]+\\-+)|([A-Za-z0-9]+\\.+)|([A-Za-z0-9]+\\++))*[A-Za-z0-9]+@((\\w+\\-+)|(\\w+\\.))*\\w{1,63}\\.[a-zA-Z]{2,})$/\n...\n')

我还尝试scope通过以下方式定义它,结果相同:

scope :not_match_email_regex, :conditions => ["email REGEXP '(|(([A-Za-z0-9]+_+)|([A-Za-z0-9]+\-+)|([A-Za-z0-9]+\.+)|([A-Za-z0-9]+\++))*[A-Za-z0-9]+@((\w+\-+)|(\w+\.))*\w{1,63}\.[a-zA-Z]{2,})'"]

它生成的查询是:

SELECT `users`.* FROM `users` WHERE (email REGEXP '(|(([A-Za-z0-9]+_+)|([A-Za-z0-9]+-+)|([A-Za-z0-9]+.+)|([A-Za-z0-9]+++))*[A-Za-z0-9]+@((w+-+)|(w+.))*w{1,63}.[a-zA-Z]{2,})')

如何获取与给定正则表达式匹配或不匹配的所有记录?

4

2 回答 2

2

部分根据@innocent_rifle 的评论编辑 12-11-30小修正

这里建议的正则表达式试图进行与原始问题相同的匹配

1.在我第一次编写解决方案时,我忘记了必须\在字符串中转义,因为我直接在 MySQL 中进行测试。在讨论正则表达式时,在字符串中使用正则表达式会让人感到困惑,所以我将使用这种形式来代替,例如/dot\./.sourcewhich (in Ruby) will give "dot\\.".

2. MySQL 中的REGEXP(5.6 手动,5.0.67 测试)使用的是“C escape syntax in strings”,所以WHERE email REGEXP '\.'还是一样WHERE email REGEXP '.',找到你必须使用的字符"."WHERE email REGEXP '\\.'实现你必须使用的代码.where([ 'email REGEXP ?', "\\\\."])。使用起来更具可读性.where([ 'email REGEXP ?', /\\./.source ])(MySQL 需要 2 次转义)。但是,我更喜欢使用.where([ 'email REGEXP ?', /[.]/.source ]),那么我不必担心您需要多少转义。

3.你不需要"-"在正则表达式中转义,[]只要该字符是第一个或最后一个,就不需要转义。


我发现了一些错误:这是第一个正则表达式或“|” 在你的表达中,它应该作为查询中的字符串,或者使用我更喜欢的 Regexp#source。我认为最后还有一个额外的报价。除此之外,您真的确定正则表达式有效。如果您在控制台中尝试使用字符串?

另请注意,您不会在 db 中捕获带有 NULL 的电子邮件,在这种情况下,您必须添加(<your existing expr in parentheses>) OR IS NULL

我的 MySQL 版本中的正则表达式语法。

我还测试了@Olaf Dietsche 在他的建议中写的内容,似乎不需要,但强烈建议无论如何都遵循标准语法NOT (expr REGEXP pat)(或expr NOT REGEXP pat)。

我做了一些检查,这些东西必须改变:使用[A-Za-z0-9_]而不是\w,并且\+无效,你必须使用\\+"\\\\+"如果字符串),更容易使用[+](在正则表达式或字符串中)。

它导致在 MySQL 中遵循 REGEXP

'^(([A-Za-z0-9]+_+)|([A-Za-z0-9]+-+)|([A-Za-z0-9]+[.]+)|([A-Za-z0-9]+[+]+))*[A-Za-z0-9]+@(([A-Za-z0-9]+-+)|([A-Za-z0-9]+[.]))*[A-Za-z0-9]{1,63}[.][a-zA-Z]{2,}$'

小改动建议

我不完全理解你的正则表达式,所以这只是改变你的正则表达式而不改变它会找到的内容。

第一:按照我上面的描述改变整个字符串

然后改变

(([A-Za-z0-9]+_+)|([A-Za-z0-9]+-+)|([A-Za-z0-9]+[.]+)|([A-Za-z0-9]+[+]+))*

([A-Za-z0-9]+[-+_.]+)*

@(([A-Za-z0-9]+-+)|([A-Za-z0-9]+[.]))*

@([A-Za-z]+[-.]+)*

最终代码..., :conditions => ...(如果您愿意,可以更改为语法)。我试图让它找到与@innocent_rifle评论中相同的字符串"_",只在右侧添加表达式@

.where([ 'NOT (email REGEXP ?)', /^([A-Za-z0-9]+[-+_.]+)*[A-Za-z0-9]+@([A-Za-z0-9]+[-._]+)*[A-Za-z0-9_]{1,63}[.][A-Za-z]{2,}$/.source ])
于 2012-11-23T13:42:52.623 回答
0

对于验证电子邮件地址,您可能需要考虑如何查找或验证电子邮件地址。至少,这个正则表达式看起来更简单一些。

根据MySQL - 正则表达式,正确的语法是

expr REGEXP pat

比赛,和

expr NOT REGEXP pat或者NOT (expr REGEXP pat)

相反。不要忘记第二个版本中的大括号。

于 2012-11-23T14:10:01.293 回答