Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/regex/19.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 锚定到最后一场比赛结束_Python_Regex_Search_Match_Repeat - Fatal编程技术网

Python 锚定到最后一场比赛结束

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修饰符。我将使用的正则表达式将匹配引号外的字符或后跟,'的带引号的字符串: ('[^']*'|[^',]

在开发过程中,我偶然发现了Python重复正则表达式的一个异常

假设给我一个CSV字符串,其中包含任意数量的带引号和不带引号的元素:

21,2,'23.5R25 ETADT','description,带逗号'

我想用
'\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逗号
  • \s*
    -0或更多空格
  • ([^',]*(?:“[^']*”[^',]*)*)
    -组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'