Python re.split并将匹配的组附加到拆分的右侧或左侧

时间:2015-02-09 02:39:20

标签: python regex split

从这个例子:

>>> re.split('(\W)', 'foo/bar spam\neggs')
['foo', '/', 'bar', ' ', 'spam', '\n', 'eggs']

是否有一种直接的方法将捕获组与拆分的右侧或左侧部分相关联?例如。使用相同的正则表达式/捕获组,但屈服:

['foo', '/bar', ' spam', '\neggs']

或可选

['foo/', 'bar ', 'spam\n', 'eggs']

我确信你可以通过更改实际的正则表达式来实现它,但这不是重点(我们可以修改示例以使匹配变得更复杂,所以这真的很痛苦无法重新使用它们并向右或向左推动它们。

不幸的是,它似乎使它成为非捕获组只是从匹配中删除相应的字符:

>>> re.split('(?:\W)', 'foo/bar spam\neggs')
['foo', 'bar', 'spam', 'eggs']

通过另一个示例,考虑您是否有来自行为不当的CSV文件的文本。每行只有一个实际的逗号可以拆分,但是偶然某些行在其中一个字段中也有逗号。幸运的是,非分裂逗号后面总是有一个空格。

csv_data = [
    'Some good data,Id 5',
    'Some bad data, like, really bad, dude,Id 6'
]

这种情况下的目标是将其处理为:

[['Some good data', 'Id 5'],
 ['Some bad data, like, really bad, dude', 'Id 6']]

通过使用简单的re.split

使用map(lambda x: re.split(",(?:\S)", x), csv_data)生成

[['Some good data', 'd 5'], 
 ['Some bad data, like, really bad, dude', 'd 6']]

并使用map(lambda x: re.split(",(\S)", x), csv_data)生成

[['Some good data', 'I', 'd 5'],
 ['Some bad data, like, really bad, dude', 'I', 'd 6']]

那么re.split的通用方法对于这两种情况都有同样的作用吗?基本上我可以在函数中包装,比如

def my_split(regex_chars, my_strs):
    return map(lambda x: re.split(...regex_chars..., x), my_strs)

这两个

my_split(r'(\W)', ['foo/bar spam\neggs']) 

my_split(r',(\S)', csv_data) 

每个都从上面返回预期的输出。

注意:仅re显示这是不可能的,但根据是否分割,可能会混合使用regexre是零宽度还是没有。

2 个答案:

答案 0 :(得分:3)

不,这是不可能的。我不知道任何支持此类事情的正则表达式引擎。拆分意味着拆分:您可以保留拆分器或者您可以丢弃它,但是您不能将它与拆分之间的碎块混在一起,因为分隔符与它分离的东西不同。

使用regex模块,您可以相当简单地完成它,但它确实需要更改原始正则表达式:

>>> regex.split('(?=\W)', 'foo/bar spam\neggs', flags=regex.V1)
['foo', '/bar', ' spam', '\neggs']

与内置re模块不同,regex模块允许拆分零宽度匹配,因此您可以使用前瞻分割在下一个字符与\W匹配的位置。< / p>

在您在编辑中添加的示例中,即使使用普通re也可以使用前瞻功能,因为拆分器不是零宽度:

>>> map(lambda x: re.split(",(?=\S)", x), csv_data)
[['Some good data', 'Id 5'],
 ['Some bad data, like, really bad, dude', 'Id 6']]

答案 1 :(得分:2)

在这种情况下,您可以使用基于负面预测的正则表达式,如下所示。

>>> csv_data = [
    'Some good data,Id 5',
    'Some bad data, like, really bad, dude,Id 6'
]
>>> [re.split(r',(?!\s)', i) for i in csv_data]
[['Some good data', 'Id 5'], ['Some bad data, like, really bad, dude', 'Id 6']]

,(?!\s)匹配所有逗号后面都没有空格字符。根据匹配的逗号分割将为您提供所需的输出。