【问题标题】:Why does this regex result in four items?为什么这个正则表达式会产生四个项目?
【发布时间】:2016-09-09 05:53:23
【问题描述】:

我想用->=> 或用多个空格包裹的字符串拆分字符串,这意味着我可以从以下字符串中获得两个项目shehe正在拆分:
"she he", "she he", "she he ", "she he ", "she->he", "she ->he", "she=>he", "she=> he", " she-> he ", " she => he \n"

我试过用这个:

re.compile("(?<!^)((\\s*[-=]>\\s*)|[\\s+\t])(?!$\n)(?=[^\s])").split(' she  -> he \n')

我得到的是一个包含四个项目的列表:[' she', ' -&gt; ', ' -&gt; ', 'he \n']

为此,

re.compile("(?<!^)((\\s*[-=]>\\s*)|[\\s+\t])(?!$\n)(?=[^\s])").split('she he')

我明白了:['she', ' ', None, 'he']

为什么有四个项目?没有中间的两个,我怎么能只得到两个?

【问题讨论】:

  • split 保留捕获组的内容。使它们全部不被捕获。
  • 在将字符串传递给 pattern.split 之前,您不能执行 string.strip() 吗?让它更干净一点。
  • 尝试使用re.findall(...)re.findall('\w+', " she -&gt; he \n") 将提供['she', 'he']
  • 根据documentation on re.split:If capturing parentheses are used in pattern, then the text of all groups in the pattern are also returned as part of the resulting list.@Rawing 向您解释了原因。您的模式相当复杂,因此除非您真的需要如此严格的检查,否则通过 pre-strip() 使用更简单的正则表达式的方法可能更可取。

标签: python regex split


【解决方案1】:

如果你可以去掉你的输入字符串。根据您的描述,您只需要拆分\s+\s*-&gt;\s*\s*=&gt;\s* 上的单词

所以这是我的解决方案:

p = re.compile(r'\s*[-=]>\s*|\s+')
input1 = "she he"
input2 = " she  -> he \n".strip()

print p.split(input1)
print p.split(input2)

您的输出将只是“她”和“他”:

['she', 'he']

【讨论】:

    【解决方案2】:

    正如 cmets 已经指出的那样,正则表达式中的每对括号构成一个捕获组,每个括号都由正则表达式 split() 函数返回。根据documentation

    如果在模式中使用捕获括号,则模式中所有组的文本也会作为结果列表的一部分返回。

    Python 正则表达式具有非捕获括号的功能。你使用(?: 而不是( 作为左括号来分组而不捕获。

    >>> re.compile("(?<!^)((\\s*[-=]>\\s*)|[\\s+\t])(?!$\n)(?=[^\s])").split('she he')
    ['she', ' ', None, 'he']
    >>> re.compile("(?<!^)(?:(?:\\s*[-=]>\\s*)|[\\s+\t])(?!$\n)(?=[^\s])").split('she he')
    ['she', 'he']
    

    目前还不清楚为什么要在字符类中显式包含一个带有\s 的制表符; \s 已经包含制表符作为它匹配的许多空白字符之一。

    也不清楚您期望$\n 匹配什么。 $ 是行尾,\n 是文字换行符,因此您似乎正在尝试处理换行符;但仅$ 就已经涵盖了这一点。 $$\n 之间的唯一区别是,如果字符串的结尾(多行字符串中的最后一行)不是换行符终止的,则不会匹配后者。

    (?&lt;!^) 也很特殊——避免匹配空字符串的更好方法是确保您的正则表达式始终匹配某些内容。

    从你的要求看来,

    re.compile(r'\s*[-=]>\s*|\s+').split('he she')
    

    会更简洁易读地做你想做的事。这将匹配两侧带有可选空格的 ASCII 箭头(单笔或双笔),或者如果失败,则回退到一系列空格。

    【讨论】:

    • 很好的答案,如果在上面的例子中使用'she -> he \n',仍然会给他留下空字符串。我建议在结果上使用“filter()”。
    • 非常感谢您的详细解释。
    【解决方案3】:

    每次使用括号“()”时,您都在创建一个捕获组。捕获组是匹配的一部分。匹配总是指完整的正则表达式字符串。这就是为什么你会得到 4 个结果。

    文档说:"If capturing parentheses are used in pattern, then the text of all groups in the pattern are also returned as part of the resulting list."

    您可以尝试按照 Rawing 的建议将组设置为“非捕获”。只需在您不想被捕获的括号内添加“?:”即可。

    我会完全省略括号:

    res = re.compile("\\s*[-=]>\\s*|\\s*").split(' she  -> he \n')
    res = filter(None, res)
    res = list(res)
    

    输出:

    ['she', 'he']
    

    【讨论】:

      猜你喜欢
      • 2010-09-22
      • 1970-01-01
      • 1970-01-01
      • 2018-07-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-08-24
      相关资源
      最近更新 更多