3

由于 jQuery 处理脚本标签的方式,我发现有必要使用正则表达式进行一些 HTML 操作(是的,我知道......这不是这项工作的理想工具)。不幸的是,我对捕获的组如何在 JavaScript 中工作的理解似乎存在缺陷,因为当我尝试这样做时:

var scriptTagFormat = /<script .*?(src="(.*?)")?.*?>(.*?)<\/script>/ig;

html = html.replace(
    scriptTagFormat, 
    '<span class="script-placeholder" style="display:none;" title="$2">$3</span>');

脚本标签被跨度替换,但结果title属性为空白。不应该$2匹配src脚本标签的属性内容吗?

4

5 回答 5

4

组的嵌套无关紧要;它们的编号严格取决于它们在正则表达式中的左括号的位置。在您的情况下,这意味着它是第 1 组捕获整个src="value"序列,第 2 组仅捕获value部分。

于 2011-05-05T20:42:51.840 回答
1

.*?匹配太多,因为以下组是可选的,==> 你的src匹配来自.*?周围的一个。如果您?在第一组之后删除它,它会起作用。

更新:正如@morja 指出的那样,您的解决方案是将第一个.*?移入可选的 src 部分。

只是为了完整性:/<script (?:.*?(src="(.*?)"))?.*?>(.*?)<\/script>/ig

您可以在 rubular 上看到它(也更正了我的链接)

如果您不想使用第一个捕获组的内容,则使用使其成为非捕获组(?:)

/<script (?:.*?(?:src="(.*?)"))?.*?>(.*?)<\/script>/ig

那么你想要的结果是 1 美元和 2 美元。

于 2011-05-05T20:44:44.587 回答
1

试试这个:

/<script (?:(?!src).)*(?:src="(.*?)")?.*?>(.*?)<\/script>/ig

见这里:rubular

As stema wrote, the .*? matches too much. With the negative lookahead (?:(?!src).)* you will match only until a src attribute.

But actually in this case you could also just move the .*? into the optional part:

/<script (?:.*?src="(.*?)")?.*?>(.*?)<\/script>/ig

See here: rubular

于 2011-05-05T22:26:21.310 回答
0

你能发布你正在检索的html吗?您的代码在一个简单的示例中运行良好:jsfiddle (warning: alert box)

我的第一个猜测是您的一个脚本标签没有 src 意味着您只剩下一个捕获组(脚本内容)。

于 2011-05-05T20:36:20.973 回答
0

我认为正则表达式本身不能完全满足我的要求,所以这是我为解决这个问题所做的修改:

var scriptTagFormat = /<script\s+((.*?)="(.*?)")*\s*>(.*?)<\/script>/ig;

html = html.replace(
    scriptTagFormat, 
    '<span class="script-placeholder" style="display:none;" $1>$4</span>');

之前,我想避免在替换上设置非标准属性span。此代码改为盲目复制所有属性。幸运的是,当我插入 HTML 时,非标准属性并没有从 DOM 中删除,因此它适用于我的目的。

于 2011-05-05T22:15:31.467 回答