【问题标题】:Regex for ignoring a character in a search用于忽略搜索中的字符的正则表达式
【发布时间】:2012-03-13 21:04:13
【问题描述】:

我有一个要求,我需要将“testuser”或“joeperson”等文本与“test.user”或“joe.person”等数据进行匹配。我不知道实际数据中传入搜索词中的句点在哪里。简而言之,我们有像 /cart/[user name which can have a period]/items/ 这样的 URL,我需要搜索与该模式匹配的所有用户名。

我正在对 MySQL 数据库使用 Django 和 Python。我知道我可以执行如下 Django 查询:

User.objects.filter(username__regex='[some crazy pattern]') 但这是我需要帮助的疯狂模式。

非常感谢!

【问题讨论】:

  • 你不能只从字符串中删除句点,然后用你的新的、清理过的字符串进行常规搜索吗?
  • 不,数据库中的数据可能有句号,认为是正确的。这是没有句号的搜索词。
  • 为什么不将数据库数据保存为没有句点的规范化形式?正则表达式会很慢。
  • @NiklasB。是的,这会起作用,但在这种情况下,我们无权访问此数据库。所以我不得不捏造它。
  • 我看到的最简单的解决方案是WHERE REPLACE(your_column, '.', '') = 'your_username_without_periods',但它的效率会非常低。

标签: python mysql regex django


【解决方案1】:

使用如下 SQL 查询:

SELECT * FROM users WHERE REPLACE(username, '.', '') = 'username_without_dots'

或者在 Django 中:

normalized_name = searchterm.replace('.', '')
User.objects.raw('SELECT * FROM user WHERE '
                 'REPLACE(username, '.', '') = %s', 
                 [normalized_name])

【讨论】:

  • 这将是非常低效的,因为您不能使用 MySQL 对计算列进行索引。 OP 可能应该为没有句点的用户名创建第二列,但因为他无法修改他的数据库......
  • @VincentSavard:是的,它效率低下,但是没有能力改变数据,我认为这是唯一的方法(至少比正则表达式更好;)
  • 请交叉手指不要让 paul.omaha paulo.maha 两个都在你的桌子上!
  • @sidyll:嘿,是的,还有另一个原因是让数据保持标准化形式。
  • 谢谢@NiklasB。这行得通。我希望使用正则表达式并让它更快,但这会很好。
【解决方案2】:

为更简洁地使用“?”而进行了编辑与“{0,1}”

当然,真正的问题是,将字段查找交给您的是谁/无论什么都没有正确准备它,但 regEx 不一定比使用文字字符串循环整个集合要慢得多。

RegEx 匹配是连续的,因此您必须为 'testuser' where '.' 执行类似的操作字母之间的字符是可选的。这实际上并没有 regEx 的那么慢,因为它应该在第二个字符不匹配并且所有字符都是显式的时失败,因此您不会为每个字符消耗大量索引。

r'^t\.?e\.?s\.?t\.?u\.?s\.?e\.?r$'

重要的部分是你的普通字符之间的空间。对于 >=0 '.'你可以做的字符。*当然我假设没有句号开始或结束。如果你可以连接,你应该能够处理。

要创建第一个正则表达式,我会执行以下操作:

user = user.split('')
userRegEx = '\.?'.join(user)

#not sure I have the right syntax for the Django arg

User.objects.filter(username__regex=r'^'+userRegEx+'$')

作为一个 JS 人,我不得不说我有点困惑,为什么 Python 社区没有想到字符串和列表都可以有一个 .join 方法。

【讨论】:

  • 另外,如果您可以确定第一个字符不是 '.'首先使用某种“以首字母开头”查询来缩小范围可能会稍微减少工作量。
  • 来吧,你可以把每个\.{0,1}替换成\.?
  • 完全忘记了单字符的使用。我只是认为它是多字符匹配的惰性切换器。我会编辑。
  • 回复您的最后一条评论:哈哈,猜猜您没有想到要尝试一下:字符串是“可迭代对象”,因此您可以说r"\.".join("hello there"),它就可以工作。我简化了你的解决方案。
  • 有趣。在 JS 中也是如此,但您仍然必须在 args 中放置一个空字符串。
【解决方案3】:

尝试使用反斜杠来转义正则表达式中的句点,如下所示:

# This will work for test.user or joe.person
re.search('(\S+)\.(\S+)', 'test.user')

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-06-04
    • 1970-01-01
    • 2019-04-13
    • 1970-01-01
    • 2018-05-14
    • 2019-07-01
    • 2014-10-21
    • 2014-03-04
    相关资源
    最近更新 更多