我有一个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,})$/i"在active record的帮助下,我想从数据库中获取电子邮件地址与此regexp不匹配的所有用户。为了达到预期的效果,我尝试了下面的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,})')如何获取与给定正则表达式匹配或不匹配的所有记录?
发布于 2012-11-23 21:42:53
根据@innocent_rifle的评论编辑12-11-30小更正
这里建议的正则表达式试图进行与原始问题中相同的匹配
1.在我的解决方案中,当我第一次编写它时,我忘记了必须在字符串中转义\,因为我是直接在MySQL中测试的。当讨论Regexps时,在字符串中使用Regexps是很混乱的,所以我将使用这种形式,例如/dot\./.source,它(在"dot\\."中)将提供Regexps。
2. REGEXP in MySQL (手册为5.6,测试版本为5.0.67)都使用"C在字符串中转义语法“,所以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。我想在结尾处还有一句额外的话。除此之外,您是否真的确定regexps可以正常工作。如果您在控制台中对字符串进行尝试?
还要注意,您不会捕获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,并且\+无效,你必须使用\\+ (如果是string,则使用"\\\\+"),使用[+] (在Regexp或string中)更容易。
它导致在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,}$'小零钱建议
我不能准确地理解您的regexp,所以这只是更改您的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-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-23 22:10:01
对于验证电子邮件地址,您可能需要考虑使用How to Find or Validate an Email Address。至少,这个regexp看起来简单一点。
根据MySQL - Regular Expressions的说法,正确的语法是
expr REGEXP pat
用于匹配,并且
expr NOT REGEXP pat或NOT (expr REGEXP pat)
正好相反。不要忘记第二个版本中的花括号。
https://stackoverflow.com/questions/13529937
复制相似问题