Regex 为什么我的正则表达式如此懒惰?

Regex 为什么我的正则表达式如此懒惰?,regex,Regex,为什么这个正则表达式如此懒惰?它应该反向引用一个height/width属性,填充中间的内容(可选),然后再引用另一个height/width属性(可选)。它只获取第一个属性,然后即使可以匹配更多属性也会退出 ((?:height|width)=["']\d*["'])([\s\w:;'"=])*?((?:height|width)=["']\d*["'])? 查看发生了什么的最简单方法是将其分解为扩展格式。在扩展格式中,您的正则表达式 ((?:height|width)=["']\d*["'

为什么这个正则表达式如此懒惰?它应该反向引用一个height/width属性,填充中间的内容(可选),然后再引用另一个height/width属性(可选)。它只获取第一个属性,然后即使可以匹配更多属性也会退出

((?:height|width)=["']\d*["'])([\s\w:;'"=])*?((?:height|width)=["']\d*["'])?

查看发生了什么的最简单方法是将其分解为扩展格式。在扩展格式中,您的正则表达式

((?:height|width)=["']\d*["'])([\s\w:;'"=])*?((?:height|width)=["']\d*["'])?
然后变成(带有注释,以扩展格式合法):

因此,您的正则表达式可能会生成1个组,最多生成N个组,具体取决于您使用的正则表达式引擎。你的最后一组将是你想要的组,如果它在那里的话。删除第二组的惰性修饰符(
),并使第二组不捕获,如下所示:

(                     # a group that captures...
    (?:height|width)  # Height or width (non capturing)
    =                 # The Equals sign
    ["']              # a double quote or quote
    \d*               # zero or more digits 0-9
    ["']              # a double quote or quote
)                     # requried
(?:                   # zero or more groups of space chars, letters, 
    [\s\w:;'"=]       # numbers, colon, quote, dobule quote, and equals 
)*                    # zero or more times as much as it can UNTIL...
(                     # a group that captures...
    (?:height|width)  # height or width (non-capturing)
    =                 # colon
    ["']              # double quote or quote
    \d*               # zero or more numbers
    ["']              # double quote or quote
)?                    # optional

现在,第一个和最后一个标签将分别在组1和2中,中间的东西被忽略。如果有最后一个,它将被捕获

注意:它可能没有捕获最后一部分,因为没有指定中间组需要捕获的字符。比如说,如果有逗号、一个

#
或任何其他类型的标记字符,则它们不是由中间组的字符类指定的。你可以考虑用:

替换中间的那一个。
    ["']              # a double quote or quote
)                     # requried
.*                    # Anything, zero or more times, UNTIL...
(                     # a group that...
    (?:height|width)  # height or width (non-capturing)
看看是否匹配。如果是的话,你可能需要进一步提高你的中间群体的性格等级

如果你不关心中间组中发生了多少匹配,只要你捕获它,使用一个非捕获组捕获每个子集,然后使用一组来捕获中间组的整个集合:

    ["']              # a double quote or quote
)                     # requried
(                     # a group that captures...
    (?:               # zero or more groups of space chars, letters, 
        [\s\w:;'"=]   # numbers, colon, quote, dobule quote, and equals 
    )*                # zero or more times as much as it can
)                     # UNTIL...
(                     # a group that captures...
    (?:height|width)  # height or width (non-capturing)

现在,您将拥有固定数量的捕获,第一部分始终在组1中,中间部分始终在组2中,最后一部分(如果有)在组3中。

查看发生了什么的最简单方法是将其分解为扩展格式。在扩展格式中,您的正则表达式

((?:height|width)=["']\d*["'])([\s\w:;'"=])*?((?:height|width)=["']\d*["'])?
然后变成(带有注释,以扩展格式合法):

因此,您的正则表达式可能会生成1个组,最多生成N个组,具体取决于您使用的正则表达式引擎。你的最后一组将是你想要的组,如果它在那里的话。删除第二组的惰性修饰符(
),并使第二组不捕获,如下所示:

(                     # a group that captures...
    (?:height|width)  # Height or width (non capturing)
    =                 # The Equals sign
    ["']              # a double quote or quote
    \d*               # zero or more digits 0-9
    ["']              # a double quote or quote
)                     # requried
(?:                   # zero or more groups of space chars, letters, 
    [\s\w:;'"=]       # numbers, colon, quote, dobule quote, and equals 
)*                    # zero or more times as much as it can UNTIL...
(                     # a group that captures...
    (?:height|width)  # height or width (non-capturing)
    =                 # colon
    ["']              # double quote or quote
    \d*               # zero or more numbers
    ["']              # double quote or quote
)?                    # optional

现在,第一个和最后一个标签将分别在组1和2中,中间的东西被忽略。如果有最后一个,它将被捕获

注意:它可能没有捕获最后一部分,因为没有指定中间组需要捕获的字符。比如说,如果有逗号、一个

#
或任何其他类型的标记字符,则它们不是由中间组的字符类指定的。你可以考虑用:

替换中间的那一个。
    ["']              # a double quote or quote
)                     # requried
.*                    # Anything, zero or more times, UNTIL...
(                     # a group that...
    (?:height|width)  # height or width (non-capturing)
看看是否匹配。如果是的话,你可能需要进一步提高你的中间群体的性格等级

如果你不关心中间组中发生了多少匹配,只要你捕获它,使用一个非捕获组捕获每个子集,然后使用一组来捕获中间组的整个集合:

    ["']              # a double quote or quote
)                     # requried
(                     # a group that captures...
    (?:               # zero or more groups of space chars, letters, 
        [\s\w:;'"=]   # numbers, colon, quote, dobule quote, and equals 
    )*                # zero or more times as much as it can
)                     # UNTIL...
(                     # a group that captures...
    (?:height|width)  # height or width (non-capturing)

现在,您将有固定数量的捕获,第一部分始终在组1中,中间部分始终在组2中,最后一部分(如果有)在组3中。

除非您的正则表达式正在执行,否则标记在这里并不合适。您是否检查了所有组?这似乎为我选择了所有的高度和宽度?@BFTrick这有帮助吗?它什么也没做吗?有什么事吗?除非你的正则表达式在做,否则标签在这里不是很合适。你在检查所有的组吗?这似乎为我选择了所有的高度和宽度?@BFTrick这有帮助吗?它什么也没做吗?有什么吗?很好的分析,但我对OP要求的理解是第二个高度/宽度属性是可选的,所以我不认为这是完全正确的。也许我误解了?嗯。没错。“修好它。”罗伯特·P——我认为你的分析很有帮助。我没有想到要转换成扩展形式来简化解释。非常有用的方法,所以+1。@gbulmer:谢谢。:)我觉得有趣的是,大多数程序员都认为在一行代码中编写整个程序是不可接受的,但在一行上编写正则表达式(实际上,专门设计一种字符串标记语言状态序列的编程语言)非常正常。哇,多好的回答啊!谢谢你提供关于扩展格式的信息。还有两个小问题。1) 我需要这三组数据。我将用修改过的数据替换它们。2) 我认为问题是第三组太懒了,所以它不需要抓取任何东西。它让第二组可以抓取所有东西。当我替换字符串时,这会抛出我的修改。有没有一个好的在线工具来测试正则表达式并替换其中的某些部分?非常好的分析,但我对OP要求的理解是第二个高度/宽度属性是可选的,所以我不认为这是完全正确的。也许我误解了?嗯。没错。“修好它。”罗伯特·P——我认为你的分析很有帮助。我没有想到要转换成扩展形式来简化解释。非常有用的方法,所以+1。@gbulmer:谢谢。:)我觉得有趣的是,大多数程序员都认为在一行代码中编写整个程序是不可接受的,但在一行上编写正则表达式(实际上,专门设计一种字符串标记语言状态序列的编程语言)非常正常。哇,多好的回答啊!谢谢你提供关于扩展格式的信息。还有两个小问题。1) 我需要这三组数据。我将用修改过的数据替换它们。2) 我认为问题是第三组太懒了,所以它不需要抓取任何东西。它让第二组可以抓取所有东西。当我替换字符串时,这会抛出我的修改。有没有