【问题标题】:strange output regular expression r'[-.\:alnum:](.*)'奇怪的输出正则表达式 r'[-.\:alnum:](.*)'
【发布时间】:2019-02-18 22:43:43
【问题描述】:

我希望获取“-”之后的所有字母数字字符 举个例子:

>>> str1 = "12 - mystr"
>>> re.findall(r'[-.\:alnum:](.*)',  str1)
[' mystr']

首先,奇怪的是空白被认为是字母数字,而我希望得到 ['mystr']。

其次,如果没有“-”,我不明白为什么可以获取它:

>>> str2 = "qwertyuio"
>>> re.findall(r'[-.\:alnum:](.*)',  str2)
['io']

【问题讨论】:

  • 错了。应该是-\s*([[:alnum:]]+)。 Python 的 re 也不支持 POSIX 字符类。请改用-\s*(\w+)

标签: python regex


【解决方案1】:

首先,Python re does not support POSIX 字符类。

空格不被视为字母数字,您的第一个模式将-[-.\:alnum:] 匹配,然后(.*) 将除换行符之外的所有0 个或多个字符捕获到第1 组中。 [-.\:alnum:] 模式匹配一​​个字符,即-.:alnum。因此,当针对 qwertyuio 运行时,u 被匹配,io 被捕获到第 1 组。

字母数字字符可以与[^\W_] 模式匹配。因此,要捕获 - 之后的所有字母数字字符,然后是 0+ 个空格,您可以使用

re.findall(r'-\s*([^\W_]+)', s)

regex demo

详情

  • - - 一个连字符
  • \s* - 0+ 个空格
  • ([^\W_]+) - 捕获组 1:一个或多个 (+) 字母或数字字符。

Python demo:

print(re.findall(r'-\s*([^\W_]+)', '12 - mystr')) # => ['mystr']
print(re.findall(r'-\s*([^\W_]+)', 'qwertyuio'))  # => []

【讨论】:

    【解决方案2】:

    您的正则表达式说:“找到任意一个字符 -.:alnum,然后将任意数量的任意字符捕获到第一个捕获组中”。

    在第一次测试中,它找到- 作为第一个字符,然后在第一个捕获组中捕获mystr。如果任何组在正则表达式中,findall 返回找到的组列表,而不是匹配项,因此不包括匹配的 -

    您的第二个测试发现 u-.:alnum 字符之一(因为没有一个 qwerty 匹配任何字符),然后捕获并返回其余的 io

    正如@revo 在 cmets 中指出的那样,[....] 是一个字符类 - 匹配其中的任何一个字符。为了在其中包含一个 POSIX 字符类(如[:alnum:]),您需要两组括号。此外,字符类中没有顺序;您在其中包含 - 的事实仅意味着它将是匹配的字符之一,not 没有它,字母数字字符将被匹配。最后,如果你想匹配任意数量的字母数字,你的量词 * 就错了。

    因此,“匹配-,然后是任意数量的字母数字字符”将是-([[:alnum:]]*)除了...Python does not support POSIX character classes。所以你必须自己写:-([A-Za-z0-9]*)

    但是,这与您的字符串不匹配,因为正如您所注意到的,中间的空格不是一个字母数字字符。为了说明这一点,-\s*([A-Za-z0-9]*)

    【讨论】:

    • 请注意,“您需要两组括号”并不总是正确的。 ICU 正则表达式库允许使用“裸”POSIX 字符类,[:digit:]+ 匹配一个或多个数字。
    • @WiktorStribiżew “为了在其中包含一个 POSIX 字符类”。在您的示例中,POSIX 字符类是独立的,没有嵌入到另一个字符类表达式中。
    • 如果您参考我的评论,是的,它是“独立的”,并且它在 ICU 正则表达式中工作。在 R stringr 函数(如 str_extract)或 Swift 中尝试自己。
    • @WiktorStribiżew 我的意思是,您的评论不适用于我的文字。我特别说过 embedded POSIX 类需要一对额外的括号(即[-[:alnum:]] 是“连字符或任何字母数字”,[-:alnum:] 只是“-:alnum 之一”)。正如您所说,独立的 POSIX 类可以使用一对。这在 ICU 外有效; Onigmo 做同样的事情。
    • 对不起,我在你的答案中找不到这个,因此决定提一下。此外,以防万一,在 POSIX 术语中,POSIX 字符类周围的那些“外部”括号称为括号表达式,而不是字符类。另外,我是 not sure about Ruby support 纯 POSIX 字符类。
    【解决方案3】:

    不太确定要匹配什么。我假设您不想在任何匹配项中包含“-”。

    如果您想获取第一个“-”之后的所有字母数字字符并跳过所有其他字符,您可以这样做。

    re.match('.*?(?<=-)(((?<=\s+)?[a-zA-Z\d]+(?=\s+)?)+)', inputString)
    

    如果您想在每个“-”之后查找每个字母数字字符串,那么您可以这样做。

    re.findall('(?<=-)[a-zA-Z\d]+')
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-06-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-09-17
      相关资源
      最近更新 更多