【问题标题】:python re, extract values between commaspython re,提取逗号之间的值
【发布时间】:2013-11-06 05:25:42
【问题描述】:

为什么下一个正则表达式在 'a' 和 'b' 之间返回空字符串?

In [48]: pat = re.compile(".*?(?=,|$)")

In [49]: it = pat.findall('a,b')

In [50]: it
Out[50]: ['a', '', 'b', '']

如何提取逗号之间的子字符串?

编辑: 我很好奇如何使用正则表达式。

编辑: 正则表达式应成功提取此输入“,”中的树空字符串。

【问题讨论】:

  • 你为什么不在,上分开呢? (另外,* 表示 0 或更多,所以 ...)
  • 我想了解如何使用正则表达式

标签: python regex


【解决方案1】:
  • .*? 首先匹配 a,因为下一个字符是 ,
  • 正则表达式引擎现在位于, 之前的位置。
  • 现在,.*? 匹配 , 之前的空字符串(因为星号允许零长度匹配)。
  • 正则表达式引擎在零长度匹配后前移一个字符(它必须这样做,否则会永远卡在这里)。
  • .*? 现在与 b 匹配,因为我们位于字符串的末尾。
  • 正则表达式引擎现在位于字符串的末尾。
  • .*? 匹配字符串末尾之前的空字符串。
  • 字符串已用尽。正则表达式引擎结束。

最好的解决方案是简单地用逗号分隔。

如果你坚持使用正则表达式,它会有点复杂,因为(根据docs),re.findall() 包括空匹配,除非它们触及另一个匹配的开始。这意味着我们必须使用positive lookbehind assertion 而不是您使用的前瞻。

这反过来意味着我们不能在同一个断言中检查定界符和字符串起始锚点,因为 Python 不允许在lookbehinds 中使用可变宽度的正则表达式(叹气)。但有可能是这样的:

>>> re.findall("(?:^|(?<=,))[^,]*", "a,b,,c")
['a', 'b', '', 'c']

【讨论】:

  • 如果我不想要空匹配,但我希望在两个连续的逗号“,,”上返回空字符串,该怎么办?
  • @msh - 这是一个好问题。我不认为像(?=,,)|.+?(?=,|$) 这样的东西能够在不消耗至少一个逗号的情况下通过两个,,。然后引擎只在非消费的字符上前进。
  • @msh:好的,正则表达式是可能的,但与简单的.split() 相比相当难看。查看我的编辑。
【解决方案2】:

你可以这样做:

st='a,b,   c  , d, eeeee'
data=[e.strip() for e in st.split(',')]

print data
# ['a', 'b', 'c', 'd', 'eeeee']

或者使用 csv:

for line in csv.reader(st.splitlines()):
    print line
# ['a', 'b', '   c  ', ' d', ' eeeee']  # strip as you please

或者一个正则表达式:

print re.findall(r'([^,]+)(?:,|$)', st) 
# ['a', 'b', '   c  ', ' d', ' eeeee']

编辑

这可以满足您使用正则表达式的要求:

>>> re.findall(r'[^,]+|,\s*,', 'a,b,   c  ,, d, eeeee')
['a', 'b', '   c  ', ',,', ' d', ' eeeee']

【讨论】:

    【解决方案3】:

    我认为问题在于您的整个正则表达式在前瞻断言之前由“可选”字符消耗组成。

    随着匹配位置的推进,它可以匹配某些内容或不匹配任何内容。
    当它不匹配时,数组将填充''

    所以a,b 匹配 'a'、''、'b'、''
    其中最后的 '' 是字符串的结尾(就像 .*$ 匹配空字符串)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-03-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-07-02
      相关资源
      最近更新 更多