python正则表达式:捕获包含空格的多个字符串的部分

python正则表达式:捕获包含空格的多个字符串的部分,python,regex,space,repeat,Python,Regex,Space,Repeat,我试图从一个看起来类似于的字符串中捕获子字符串 'some string, another string, ' 我希望比赛小组的结果是 ('some string', 'another string') 我当前的解决方案 >>> from re import match >>> match(2 * '(.*?), ', 'some string, another string, ').groups() ('some string', 'another st

我试图从一个看起来类似于的字符串中捕获子字符串

'some string, another string, '
我希望比赛小组的结果是

('some string', 'another string')
我当前的解决方案

>>> from re import match
>>> match(2 * '(.*?), ', 'some string, another string, ').groups()
('some string', 'another string')
工作,但不是切实可行的-我在这里展示的当然是在复杂性方面大大减少了与我在实际项目中所做的相比;我只想使用一个“直”(非计算)正则表达式模式。不幸的是,我的尝试到目前为止失败了:

这不匹配(结果为无),因为{2}仅应用于空格,而不是整个字符串:

>>> match('.*?, {2}', 'some string, another string, ')
在重复的字符串周围添加括号会在结果中使用逗号和空格

>>> match('(.*?, ){2}', 'some string, another string, ').groups()
('another string, ',)
添加另一组偏执论确实解决了这一问题,但让我感到太多了:

>>> match('((.*?), ){2}', 'some string, another string, ').groups()
('another string, ', 'another string')
添加非捕获修饰符可以改进结果,但仍然会忽略第一个字符串

>>> match('(?:(.*?), ){2}', 'some string, another string, ').groups()
('another string',)
我觉得我很接近,但我似乎找不到合适的方法

有人能帮我吗?还有其他我没有看到的方法吗


在前几个响应之后更新:

首先,非常感谢大家,非常感谢你们的帮助!:-)

正如我在原始帖子中所说,为了描述实际的核心问题,我在问题中省略了很多复杂性。首先,在我正在进行的项目中,我正在解析大量不同行格式的文件(目前每天数万个)(目前为5个,很快~25个,可能在数百个之后)。还有XML、JSON、二进制和其他一些数据文件格式,但让我们继续关注

为了处理大量的文件格式并利用其中许多是基于行的这一事实,我创建了一个有点通用的Python模块,该模块加载一个又一个文件,对每一行应用正则表达式,并返回一个包含匹配项的大数据结构。这个模块是一个原型,生产版本需要一个C++版本来执行性能,它将在Boosi::Python上连接,并且可能将ReGEX方言的主题添加到复杂列表中。 此外,没有2次重复,但数量在当前的0到70(左右)之间变化,逗号并不总是逗号,尽管我最初说过,regex模式的某些部分必须在运行时计算;让我们说,我有理由尝试减少“动态”数量,并尽可能多地使用“固定”模式

因此,一句话:我必须使用正则表达式。


尝试重新表述:我认为问题的核心归结为:是否有Python正则表达式表示法,例如,涉及大括号重复并允许我捕获

'some string, another string, '
进入

?

嗯,这可能把范围缩小得太远了——但是,不管你怎么做都是错误的:-D


第二次尝试重新表述:为什么我在结果中看不到第一个字符串(“某个字符串”)?为什么正则表达式生成一个匹配项(表示必须有2个匹配项),但只返回1个字符串(第二个)

即使我使用非数字重复,即使用+而不是{2},问题仍然是一样的:

>>> match('(?:(.*?), )+', 'some string, another string, ').groups()
('another string',)
此外,返回的不是第二个字符串,而是最后一个字符串:

>>> match('(?:(.*?), )+', 'some string, another string, third string, ').groups()
('third string',)

再次感谢您的帮助,当我试图找出我真正想知道的内容时,同行评议会给我带来多么大的帮助,我永远不会停止感到惊讶……

除非这个问题有比您解释的更多的东西,否则我不认为使用正则表达式有什么意义。使用基本字符串方法处理此问题非常简单:

import re

regex = " *((?:[^, ]| +[^, ])+) *, *((?:[^, ]| +[^, ])+) *, *"

print re.match(regex, 'some string, another string, ').groups()
# ('some string', 'another string')
print re.match(regex, ' some string, another string, ').groups()
# ('some string', 'another string')
print re.match(regex, ' some string , another string, ').groups()
# ('some string', 'another string')
[s.strip() for s in mys.split(',') if s.strip()]
或者如果它必须是一个元组:

tuple(s.strip() for s in mys.split(',') if s.strip())
代码也更具可读性。如果这不适用,请告诉我



编辑:好的,这个问题确实比最初看起来要复杂得多。但这只是出于历史目的。(我想我没有“纪律严明”:)如前所述,我认为这个正则表达式很好:

import re
thepattern = re.compile("(.+?)(?:,|$)") # lazy non-empty match 
thepattern.findall("a, b, asdf, d")     # until comma or end of line
# Result:
Out[19]: ['a', ' b', ' asdf', ' d']
这里的关键是使用而不是
匹配
。您的问题的措辞表明您更喜欢
匹配
,但它不是这里工作的正确工具——它的设计目的是为正则表达式中的每个对应组
返回一个字符串。由于“字符串数”是可变的,正确的方法是使用
findall
split

如果这不是你需要的,那么请让问题更具体

编辑:如果必须使用元组而不是列表:

tuple(Out[19])
# Result
Out[20]: ('a', ' b', ' asdf', ' d')

无意冒犯,但是你显然有很多关于正则表达式的知识需要学习,你最终会学到的是正则表达式无法处理这项工作。我确信这个特殊的任务在正则表达式中是可以完成的,但是接下来呢?你说你可能有数百种不同的文件格式需要解析!您甚至提到了JSON和XML,它们基本上与正则表达式不兼容


帮自己一个忙:忘掉正则表达式,改为学习。或者完全跳过Python,使用独立的解析器生成器,如。在任何一种情况下,您都可能会发现大多数文件格式的语法已经编写完成。

为了总结这一点,我似乎已经在使用最佳解决方案,以“动态”方式构造正则表达式模式:

>>> from re import match
>>> match(2 * '(.*?), ', 'some string, another string, ').groups()
('some string', 'another string')

这就是我所说的动态。替代方法

>>> match('(?:(.*?), ){2}', 'some string, another string, ').groups()
('another string',)
未能返回预期结果,原因是(正如Glenn和Alan善意地解释的)

使用match,捕获的内容将被覆盖 每次重复捕捉 团体

谢谢大家的帮助!:-)

我认为问题的核心在于 归结到:有Python正则表达式吗 包括卷曲的符号 支撑重复,让我 捕捉“某个字符串,另一个字符串, ”“是吗

我认为没有这样的符号

但是正则表达式并不是唯一的符号问题,也就是说用来定义正则表达式的RE字符串。它也是一个
2 * '(.*?)
>>> match('(?:(.*?), ){2}', 'some string, another string, ').groups()
('another string',)
import re

for line in ('string one, string two, ',
             'some string, another string, third string, ',
             # the following two lines are only one string
             'Topaz, Turquoise, Moss Agate, Obsidian, '
             'Tigers-Eye, Tourmaline, Lapis Lazuli, '):

    print re.findall('(.+?), *',line)
['string one', 'string two']
['some string', 'another string', 'third string']
['Topaz', 'Turquoise', 'Moss Agate', 'Obsidian', 'Tigers-Eye', 'Tourmaline', 'Lapis Lazuli']
import re

for line in ('string one, string two, ',
             'some string, another string, third string, ',
             # the following two lines are only one string
             'Topaz, Turquoise, Moss Agate, Obsidian, '
             'Tigers-Eye, Tourmaline, Lapis Lazuli, '):

    print [ mat.group(1) for mat in re.finditer('(.+?), *',line) ]