【问题标题】:Python Regex - EscapingPython 正则表达式 - 转义
【发布时间】:2012-02-06 06:09:52
【问题描述】:

我有一个 Python 正则表达式,它接受一个字符串(数据库连接 URI)并使用命名组将其拆分为用户名、密码等。

uri = 'username:password@host/database'
m = re.compile('^(?P<user>[^:@]+)(\:(?P<password>[^@]*))?@(?P<host>[^\:@/]+)(\:(?P<port>[0-9]+))?/(?P<db>[^\?]+)?$').match(uri)
print m.groupdict()
{'host': 'host', 'password': 'password', 'db': 'database', 'user': 'username', 'port': None}

这很好用。问题是 uri 中是否有 @ 符号,因为它用于拆分密码和主机。例如,

uri = 'username:p@ssword@host/database'

将不匹配,这是预期的。但是,我希望能够转义特殊字符,例如:

uri = 'username:p\@ssword@host/database'

并让它匹配。我的正则表达式经验非常有限 - 我想我想做的是修改

(?P<password>[^@]*)

group 以便它匹配任何不是 @ 的字符,除非它前面有一个 \ 字符。当然,一些(大多数)连接字符串根本不包含 \@。

非常感谢任何帮助。

【问题讨论】:

  • 为什么一开始就没有进行 URL 编码?
  • 不确定,这不是我的代码。它实际上来自 web2py。无论如何,如果它是 URL 编码的,我会不会有同样的问题,即 @'s 被替换为 %40's?他们仍然需要逃跑..
  • 不,因为正则表达式引擎不进行 URL 解码。

标签: python regex


【解决方案1】:

我的看法是你想要贪婪匹配,即密码在最后一个 @ 并且主机名在最后一个 @ 和第一个 / 之间

一个简单的方法可能是这样的:

In [68]: re.match('((?P<user>.*):)((?P<pass>.*)@)((?P<host>.*)/)((?P<db>.*))', "username:p@ssword@host/data").groupdict()
Out[68]: {'db': 'data', 'host': 'host', 'pass': 'p@ssword', 'user': 'username'}

您可能想要添加可选选项,即 (stuff)+ 如果例如用户名和密码可以省略。

【讨论】:

  • 谢谢。到处都是很好的答案,但这正是我所追求的。谢谢。
【解决方案2】:

你可以这样做:

(?P<password>([^\\@]|\\.)*)

这将扫描您的字符串并匹配:非\ 或非@,或反斜杠,在这种情况下它也匹配后面的任何内容。 '@' 可以被该正则表达式匹配的唯一方法是,如果它通过 \\. 正则表达式潜入,即它被转义了。

顺便说一句,要在 python 中编写正则表达式,请使用 r"insert_regex_here"。

否则,对于正则表达式\\.,您必须像"\\\\." 那样用python 编写它。为了避免这种情况,你可以这样做r"\\."

【讨论】:

    【解决方案3】:

    我建议你使用re.split:

    >>> print re.split(r"(?<!\\)@|/|:", r"username:password@host/database")
    ['username', 'password', 'host', 'database']
    >>> print re.split(r"(?<!\\)@|/|:", r"username:p\@ssword@host/database")
    ['username', 'p\\@ssword', 'host', 'database']
    

    【讨论】:

      猜你喜欢
      • 2013-01-18
      • 2010-12-22
      • 2014-11-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-06-10
      • 1970-01-01
      相关资源
      最近更新 更多