Python 锚定到最后一场比赛结束
在开发过程中,我偶然发现了Python重复正则表达式的一个异常 假设给我一个CSV字符串,其中包含任意数量的带引号和不带引号的元素: 21,2,'23.5R25 ETADT','description,带逗号' 我想用Python 锚定到最后一场比赛结束,python,regex,search,match,repeat,Python,Regex,Search,Match,Repeat,在开发过程中,我偶然发现了Python重复正则表达式的一个异常 假设给我一个CSV字符串,其中包含任意数量的带引号和不带引号的元素: 21,2,'23.5R25 ETADT','description,带逗号' 我想用'\t'替换所有的,'s外部引号。所以我想要一个输出: 21\t2\t“23.5R25 ETADT”\t“说明,带逗号” 由于字符串中自然会有多个匹配项,因此我将使用gregex修饰符。我将使用的正则表达式将匹配引号外的字符或后跟,'的带引号的字符串: ('[^']*'|[^',]
'\t'
替换所有的,'
s外部引号。所以我想要一个输出:
21\t2\t“23.5R25 ETADT”\t“说明,带逗号”
由于字符串中自然会有多个匹配项,因此我将使用g
regex修饰符。我将使用的正则表达式将匹配引号外的字符或后跟,'
的带引号的字符串:
('[^']*'|[^',]*),\s*
我将替换为:
\1\t
现在的问题是正则表达式正在搜索不匹配的字符,因此它可以选择跳过字符,直到匹配为止。因此,我得到的不是我想要的输出:
21\t2\t'23.5R25 ETADT'\t'description\t带逗号'
您可以在此处看到这种行为的一个实例:
有没有办法锚定一个g
modified正则表达式,以便在上次匹配后在字符处开始匹配?
对于那些熟悉Perl强大的正则表达式的人,Perl提供了。这允许我们检索最后一个匹配位置的末尾。因此,在Perl中,我可以通过正则表达式实现我的要求:
\G('[^']*'|[^',]*),\s*
这将强制在最终引用的元素中出现不匹配。因为与其允许正则表达式实现找到正则表达式与\G
匹配的点,不如强制它从以下字符的第一个字符开始匹配:
'说明,带逗号'
您可以将以下正则表达式与
re.search
一起使用:
,?\s*([^',]*(?:'[^']*'[^',]*)*)
请参阅(我将其更改为,?[]*([^',\n]*(?:“[^'\n]*”[^',\n]*)*)
,因为它是一个多行演示)
这里,regex匹配(在单词的regex含义中)
-1或0逗号,?
-0或更多空格\s*
-组1存储捕获的文本,该文本由。。。([^',]*(?:“[^']*”[^',]*)*)
-0个或更多字符,而不是[^',]*
和,
'
-0个或多个。。。(?:'[^']*'[^',]*)*
-一个类似于'[^']*'
-的子字符串,不包含撇号'string'
-0个或更多字符,而不是[^',]*
和,
'
re.match
并将捕获的文本存储在捕获组中,这是不可能的,因为Python正则表达式引擎不会像.NET正则表达式引擎使用CaptureCollection
那样将所有捕获存储在堆栈中
此外,Python正则表达式不支持\G
运算符,因此您无法在此处成功匹配结束时锚定任何子模式
作为一种替代/解决方法,您可以使用以下Python代码返回连续的匹配,然后返回字符串的其余部分:
import re
def successive_matches(pattern,text,pos=0):
ptrn = re.compile(pattern)
match = ptrn.match(text,pos)
while match:
yield match.group()
if match.end() == pos:
break
pos = match.end()
match = ptrn.match(text,pos)
if pos < len(text) - 1:
yield text[pos:]
for matched_text in successive_matches(r"('[^']*'|[^',]*),\s*","21, 2, '23.5R25 ETADT', 'description, with a comma'"):
print matched_text
看一看。或者更像是一个演示。@Stribizov是的,这两个都是可能的解决方法。如果这就是我所能做的,我也同意。但我想回答的是我们是否可以锚定这个搜索,或者强迫它匹配,而不仅仅是搜索。我想我明白了,如果你有任何疑问,请在我的答案下面加个评论。我的意思是,即使C++也能做到这一点。您只需要找到匹配的长度,然后从该点开始重新运行正则表达式。因此,即使在Python中,这也是可能的。它只需要一些正则表达式之外的腿部工作。请澄清您需要什么:从
21,2,'23.5R25 ETADT','description,with a comma'
抓取3个子字符串:21
,2
,'23.5R25 ETADT'
?我已经编辑了这个问题,但我的目标是了解如何在同一条线上锚定多场比赛。没有找到一个正则表达式可以解决Python在这种特殊情况下缺少\G
的问题。是的,就是这样。这就是我所说的,当我说它在Python中是可能的时候。该函数可以很容易地修改为只返回字符串的其余部分,以防出现不匹配的情况,在这种情况下,我们将获得我正在寻找的确切行为。我只是对我们必须为Perl的regex实现中一直存在的东西编写函数感到恼火。@每个人我都接受这个答案,因为编辑提供了Python最接近于模拟Perl的\G
功能的东西\G
是在Perl 5中引入的。我们怎么没有这个功能?
21,
2,
'23.5R25 ETADT',
'description, with a comma'