为什么这个javascript RegExp语法会无限循环?

时间:2012-02-05 15:50:52

标签: javascript regex

------------- test.hta文件代码------------

<!DOCTYPE html>
<html>
<head>
<title>dead</title>
</head>
<body>
txt<textarea id="content" >
            <input name="" type="text" class="qu_te1n05ew" value="请输入您的E-mail地址" />
           <input name="" type="submit" class="qu_sbt02" value="提 交" />
           </textarea>
<button onclick="startCls();">start</button>

<script>
function getObj(id) {
    return 'string' == typeof id ? document.getElementById(id) : id;
}

function startCls() {
    var txt = getObj('content').value;
    var srcRe = /<\w+(?:\s[^<>]*(?:(?:'[^']*')|(?:"[^"]*"))?[^<>]*)*\s+src\s*\=\s*["']?(?:[^"' <>]*\/)?([^\/"'<>]+\.(?:gif|jpg|png))['" ](?:\s[^<>]*(?:(?:'[^']*')|(?:"[^"]*"))?[^<>]*)*\/?>/ig;
    alert(srcRe.exec(txt));
}
</script>
</body>
</html>

------------代码结束-------

为什么srcRe.exec(txt)循环并且hta已经死了?但是其他测试字符串会起作用。

srcRe我的意思是获取img标记名的src,并将其拆分为获取文件名,但不要得到任何标记名的src,如<b><img src="ss.gif" </b>,因为它不是一个html标记名。未结束>;

此synax (?:\s[^<>]*(?:(?:'[^']*')|(?:"[^"]*"))?[^<>]*)*,意思是如果有<>,则必须位于''"",其他字符串必须不是<>;而是以<开头,以>结尾;

1 个答案:

答案 0 :(得分:2)

我不打算调试这个可怕的正则表达式。但我可以告诉你它失败的原因。打破它的“可读性”:

<
\w+
(?:\s[^<>]*(?:(?:'[^']*')|(?:"[^"]*"))?[^<>]*)*
\s+src\s*\=\s*["']?
(?:[^"' <>]*\/)?
([^\/"'<>]+\.(?:gif|jpg|png))
['" ]
(?:\s[^<>]*(?:(?:'[^']*')|(?:"[^"]*"))?[^<>]*)*
\/?
>

您可以看到,只有在您的字符串中有.gif.jpg.png时才能匹配。它不是,所以正则表达式必须失败。

现在的问题是正则表达式引擎需要很长时间来解决这个问题,因为你的字符串中有几个[^<>]*个实例,所有这些实例都可以(并且会尝试)匹配整个标记的内容, (以增加对伤害的伤害)所有这些都被重复组包围。见第3行,细分:

(?:
 \s
 [^<>]*       # optional!
 (?:
  (?:'[^']*')
  |
  (?:"[^"]*")
 )?           # optional!
 [^<>]*       # optional!
)*            # optional!

在能够声明失败之前,正则表达式引擎都必须检查这些排列。简而言之,它不是一个无限循环,但像这样的正则表达式,这样的输入会让你的计算机保持忙碌直到地狱冻结。

提示1:在catastrophic backtracking上阅读本教程 提示2:不要使用正则表达式来解析HTML。如果你不know exactly what you're doing,至少不会。