首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >如何用正则表达式从mysql数据库中选择记录

如何用正则表达式从mysql数据库中选择记录
EN

Stack Overflow用户
提问于 2012-11-23 21:17:50
回答 2查看 1.5K关注 0票数 0

我有一个regexp来验证用户的电子邮件地址。

代码语言:javascript
运行
复制
/^(|(([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

代码语言:javascript
运行
复制
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,})$/"]

这给出了以下查询:

代码语言:javascript
运行
复制
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,结果是一样的:

代码语言:javascript
运行
复制
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,})'"]

它生成的查询是:

代码语言:javascript
运行
复制
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,})')

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

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 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

代码语言:javascript
运行
复制
'^(([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,而不是更改它将找到的内容。

首先:按照上面的描述更改整个字符串

然后改变

代码语言:javascript
运行
复制
(([A-Za-z0-9]+_+)|([A-Za-z0-9]+-+)|([A-Za-z0-9]+[.]+)|([A-Za-z0-9]+[+]+))*

代码语言:javascript
运行
复制
([A-Za-z0-9]+[-+_.]+)*

代码语言:javascript
运行
复制
@(([A-Za-z0-9]+-+)|([A-Za-z0-9]+[.]))*

代码语言:javascript
运行
复制
@([A-Za-z]+[-.]+)*

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

代码语言:javascript
运行
复制
.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 ])
票数 2
EN

Stack Overflow用户

发布于 2012-11-23 22:10:01

对于验证电子邮件地址,您可能需要考虑使用How to Find or Validate an Email Address。至少,这个regexp看起来简单一点。

根据MySQL - Regular Expressions的说法,正确的语法是

expr REGEXP pat

用于匹配,并且

expr NOT REGEXP patNOT (expr REGEXP pat)

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

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/13529937

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档