Python re.split 并将匹配组附加到拆分的右侧或左侧
Python re.split and attaching matched group to either right or left side of the split
来自这个例子:
>>> re.split('(\W)', 'foo/bar spam\neggs')
['foo', '/', 'bar', ' ', 'spam', '\n', 'eggs']
是否有直接的方法将捕获组与拆分的右侧或左侧部分相关联?例如。使用相同的 regex/capture 组,但产生:
['foo', '/bar', ' spam', '\neggs']
或可选
['foo/', 'bar ', 'spam\n', 'eggs']
我相信您可以通过 更改 实际的正则表达式来实现它,但这不是重点(我们可以修改示例以使匹配更复杂,这样无法重复使用它们并将它们向右或向左推是一种真正的痛苦。
不幸的是,让它成为一个非捕获组似乎只是从匹配中删除相应的字符:
>>> re.split('(?:\W)', 'foo/bar spam\neggs')
['foo', 'bar', 'spam', 'eggs']
再举一个例子,考虑一下您是否有一些来自行为不当的 CSV 文件的文本。每行只有一个实际的逗号作为分隔符,但不小心有些行在其中一个字段中也有一个逗号。幸运的是,不分隔的逗号后面总是跟着 space.
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)
每个 returns 上面的预期输出。
注意:看来这在 re
中是不可能的,但在 regex
和 re
的某种混合情况下是可能的基于拆分是否为零宽度。
不,这是不可能的。我不知道有任何正则表达式引擎支持这种事情。 Splitting就是拆分:你可以保留拆分器,也可以丢弃它,但是你不能把它和拆分之间的部分混为一谈,因为分隔器和它分开的东西是不同的。
使用 regex
模块您可以相当简单地完成它,但它确实需要更改原始正则表达式:
>>> regex.split('(?=\W)', 'foo/bar spam\neggs', flags=regex.V1)
['foo', '/bar', ' spam', '\neggs']
与内置的 re
模块不同,regex
模块允许在零宽度匹配项上进行拆分,因此您可以使用先行在下一个字符匹配 \W
的位置进行拆分.
在您在编辑中添加的示例中,即使使用普通 re
也可以使用前瞻来完成,因为拆分器不是零宽度的:
>>> map(lambda x: re.split(",(?=\S)", x), csv_data)
[['Some good data', 'Id 5'],
['Some bad data, like, really bad, dude', 'Id 6']]
在这种情况下,您是否可以像下面这样使用基于负前瞻的正则表达式。
>>> 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)
匹配所有不会后跟 space 字符的逗号。根据匹配的逗号拆分将为您提供所需的输出。
来自这个例子:
>>> re.split('(\W)', 'foo/bar spam\neggs')
['foo', '/', 'bar', ' ', 'spam', '\n', 'eggs']
是否有直接的方法将捕获组与拆分的右侧或左侧部分相关联?例如。使用相同的 regex/capture 组,但产生:
['foo', '/bar', ' spam', '\neggs']
或可选
['foo/', 'bar ', 'spam\n', 'eggs']
我相信您可以通过 更改 实际的正则表达式来实现它,但这不是重点(我们可以修改示例以使匹配更复杂,这样无法重复使用它们并将它们向右或向左推是一种真正的痛苦。
不幸的是,让它成为一个非捕获组似乎只是从匹配中删除相应的字符:
>>> re.split('(?:\W)', 'foo/bar spam\neggs')
['foo', 'bar', 'spam', 'eggs']
再举一个例子,考虑一下您是否有一些来自行为不当的 CSV 文件的文本。每行只有一个实际的逗号作为分隔符,但不小心有些行在其中一个字段中也有一个逗号。幸运的是,不分隔的逗号后面总是跟着 space.
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)
每个 returns 上面的预期输出。
注意:看来这在 re
中是不可能的,但在 regex
和 re
的某种混合情况下是可能的基于拆分是否为零宽度。
不,这是不可能的。我不知道有任何正则表达式引擎支持这种事情。 Splitting就是拆分:你可以保留拆分器,也可以丢弃它,但是你不能把它和拆分之间的部分混为一谈,因为分隔器和它分开的东西是不同的。
使用 regex
模块您可以相当简单地完成它,但它确实需要更改原始正则表达式:
>>> regex.split('(?=\W)', 'foo/bar spam\neggs', flags=regex.V1)
['foo', '/bar', ' spam', '\neggs']
与内置的 re
模块不同,regex
模块允许在零宽度匹配项上进行拆分,因此您可以使用先行在下一个字符匹配 \W
的位置进行拆分.
在您在编辑中添加的示例中,即使使用普通 re
也可以使用前瞻来完成,因为拆分器不是零宽度的:
>>> map(lambda x: re.split(",(?=\S)", x), csv_data)
[['Some good data', 'Id 5'],
['Some bad data, like, really bad, dude', 'Id 6']]
在这种情况下,您是否可以像下面这样使用基于负前瞻的正则表达式。
>>> 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)
匹配所有不会后跟 space 字符的逗号。根据匹配的逗号拆分将为您提供所需的输出。