仅在第一个实例中使用正则表达式用多个分隔符分隔



我有一些字符串的格式是

lorem ipsum, dolor sit - amet, consectetur : adipiscing elit. Praesent vitae orc

我希望它在每个分离器的第一个实例中被拆分,以返回

['lorem ipsum',
'dolor sit', 
'amet, consectetur', 
'adipiscing elit. Praesent vitae orc']

现在我的输出是

['lorem ipsum',
'dolor sit',
'amet',
'consectetur ',
'adipiscing elit. Praesent vitae orc']

现在我使用的是re.split(', | - |: ', txt),但它会分离字符串中的所有实例。关于如何实现所需输出,有什么建议吗?

编辑:

我意识到我的问题不清楚,所以举个例子,如果字符串是

"abc: def: ijk, lmno: pqr - stu, wx"

输出应该是

["abc",
"def: ijk",
"lmno: pqr",
"stu, wxy"]

而不是

["abc",
"def",
"ijk",
"lmno",
"pqr",
"stu",
"wxy"]

如果所有分隔符必须至少出现一次,则可以使用4个捕获组,其中backreference与3个选项中的1个匹配,但已匹配的除外。

^(.*?)(, | - |: )(.*?)(?!2)(, | - |: )(.*?)(?!2|4)(, | - |: )(.*)

图案将与匹配

  • ^字符串开始
  • (.*?)1,尽可能少地匹配
  • (, | - |: )2,匹配任何列出的
  • (.*?)3,尽可能少地匹配
  • (?!2)否定前瞻,断言右边的不是第2组中匹配的(从2个有效选项中选择一个(
  • (, | - |: )4,匹配任何列出的
  • (.*?)5,尽可能少地匹配
  • (?!2|4)否定前瞻,断言右边的不是第2组或第4组中匹配的(选择剩下的唯一有效选项(
  • (, | - |: )6,匹配任何列出的
  • (.*)7,尽可能匹配任何字符

Regex演示

例如

import re
regex = r"^(.*?)(, | - |: )(.*?)(?!2)(, | - |: )(.*?)(?!2|4)(, | - |: )(.*)"
test_str = ("lorem ipsum, dolor sit - amet , consectetur : adipiscing elit. Praesent vitae orcnn"
"abc: def: ijk, lmno: pqr - stu, wxnn")
matches = re.search(regex, test_str, re.MULTILINE)
if matches:
print(matches.group(1))
print(matches.group(3))
print(matches.group(5))
print(matches.group(7))

输出

lorem ipsum
dolor sit
amet , consectetur 
adipiscing elit. Praesent vitae orc

参见Python demo1和demo2

只是想一想,不确定这是否是一个有价值的答案,但也许你可以使用regex而不是re模块来利用非固定宽度的负面后备功能。例如:

s*([,:-])(?<!1.*1)s*

在Python中:

import regex as re
string1 = "abc: def: ijk, lmno: pqr - stu, wx"
lst1 = re.sub(r's*([,:-])(?<!1.*1)s*', '|' , string1).split('|')
print(lst1)

结果:

['abc', 'def: ijk', 'lmno: pqr', 'stu, wx']

您可以使用一个计算替换的小类:

import re
text = "lorem ipsum, dolor sit - amet, consectetur : adipiscing elit. Praesent vitae orc"
# text = "abc: def: ijk, lmno: pqr - stu, wx"
rx = re.compile(r'[-,:]')

class Replacer:
def __init__(self, *args, **kwargs):
for key in args:
setattr(self, key, 0)
self.needle = kwargs.get("needle")
def __call__(self, match):
key = match.group(0)
setattr(self, key, getattr(self, key, 0) + 1)
cnt = getattr(self, key, 0)
return self.needle if cnt == 1 else key

rpl = Replacer("-", ",", ":", needle="#@#")
result = [item.strip() for item in re.split("#@#", rx.sub(rpl, text))]
print(result)

产生

['lorem ipsum', 'dolor sit', 'amet, consectetur', 'adipiscing elit. Praesent vitae orc']

最新更新