Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/regex/17.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 为什么re.sub会取代整个模式,而不仅仅是其中的一个捕获组?_Python_Regex_Python 3.x_Replace_Capturing Group - Fatal编程技术网

Python 为什么re.sub会取代整个模式,而不仅仅是其中的一个捕获组?

Python 为什么re.sub会取代整个模式,而不仅仅是其中的一个捕获组?,python,regex,python-3.x,replace,capturing-group,Python,Regex,Python 3.x,Replace,Capturing Group,re.sub('a(b)'d','abc')产生dc,而不是adc 为什么re.sub替换整个捕获组,而不仅仅是捕获组“(b)”?因为它应该替换整个模式: 返回通过替换repl替换字符串中模式的最左侧非重叠出现而获得的字符串 如果只替换一些子组,那么包含多个组的复杂正则表达式就不起作用。有几种可能的解决方案: 完整地指定模式:re.sub('ab'、'ad'、'abc')-我的最爱,因为它可读性和明确性很强 捕获要保留的组,然后在模式中引用它们(注意,它应该是原始字符串以避免转义):re.sub

re.sub('a(b)'d','abc')
产生
dc
,而不是
adc


为什么
re.sub
替换整个捕获组,而不仅仅是捕获组“(b)”?

因为它应该替换整个模式:

返回通过替换repl替换字符串中模式的最左侧非重叠出现而获得的字符串

如果只替换一些子组,那么包含多个组的复杂正则表达式就不起作用。有几种可能的解决方案:

  • 完整地指定模式:
    re.sub('ab'、'ad'、'abc')
    -我的最爱,因为它可读性和明确性很强
  • 捕获要保留的组,然后在模式中引用它们(注意,它应该是原始字符串以避免转义):
    re.sub('(a)b',r'\1d',abc')
  • 与前面的选项类似:提供一个回调函数作为
    repl
    参数,并使其处理
    Match
    对象并返回所需结果
  • 使用lookbehinds/lookahed,它们不包括在匹配中,但会影响匹配:
    re.sub('(?)?
    如上所述,首先我们编译一个带有不区分大小写标志的正则表达式模式


    然后我们检查文本是否与模式匹配,如果匹配,我们引用regex模式(age)中组号为\1的唯一组。

    因为这正是
    re.sub()
    doc告诉您它应该做的:

    • 模式
      'a(b)
      表示“匹配'a',并带有可选的尾随'b'”(它可以自己匹配'a',但它不可能像您所期望的那样自己匹配'b'。如果您的意思是这样的,请使用非贪婪的
      (a)??b
    • 替换字符串为“d”
    • 因此,在字符串“abc”上,它匹配所有的“ab”,并用“d”替换,因此结果是“dc”
    如果希望获得所需的输出,则需要在
    '(a)?上进行非贪婪匹配。

    >>> re.sub('(a)??b','d','abc')
    'dc'
    

    我知道这并不是严格地回答OP问题,但这个问题可能很难用谷歌搜索(被\1解释淹没了…)

    对于那些喜欢我的人来说,他们来到这里是因为他们想用字符串替换不是第一个捕获组的捕获组,而对字符串和正则表达式都不了解:

    #find offset [start, end] of a captured group within string
    r = regex.search(oldText).span(groupNb)
    #slice the old string and insert replacementText in the middle 
    newText = oldText[:r[0]] + replacementText + oldText[r[1]:]
    

    我知道这是想要的行为,但我仍然不明白为什么re.sub不能指定它应该替换的实际捕获组…

    您不在替换部分中使用它,那么您期望什么呢?如果您想将“b”替换为“a”,您需要
    re.sub('ab','ad','abc')
    re.sub('(a)b',r'\1d',abc')
    ,其中
    “\1”
    指的是捕获组。谢谢!希望捕获组被默认替换。正确的方法看起来不那么直观,但可能更灵活。@Nick:但是
    re.sub
    文档说它确实这样做,没有提到捕获组:“替换字符串中最左边的不重叠的模式”只是一个简单提示:您可以在正则表达式中使用
    \1
    re.match(r'([la]{2})-\1',la')
    。它将匹配组引用的内容(在本例中为
    1
    )matched(不是它的模式)例如,这个正则表达式与la al不匹配。@Basj:我们问过OP好几次,据我所知,他们只想解释为什么捕获组没有出现在输出中,而不是修复。@Basj:正如你从评论中看到的,我们中的一些人已经问OP他们想要什么了4年。他们从来没有说过BADOUTPUT/GOODOUTPUT,那是你的标签。他们要求解释为什么它是这样工作的。我回答了。我甚至告诉他们如何用一个可能的正则表达式得到他们想要的-见我的最后一行。
    #find offset [start, end] of a captured group within string
    r = regex.search(oldText).span(groupNb)
    #slice the old string and insert replacementText in the middle 
    newText = oldText[:r[0]] + replacementText + oldText[r[1]:]