Javascript Regex子组

时间:2012-02-20 06:56:42

标签: javascript jquery regex regex-group

首先,请勿链接到“Don't parse HTML with Regex”帖子:)

我有以下HTML,用于显示各种货币,公司和税前价格:

<span id="price_break_12345" name="1">
    <span class="price">
        <span class="inc" >
            <span class="GBP">£25.00</span>
            <span class="USD" style="display:none;">$34.31</span>
            <span class="EUR" style="display:none;">27.92&nbsp;€</span>
        </span>
        <span class="ex"  style="display:none;">
            <span class="GBP">£20.83</span>
            <span class="USD" style="display:none;">$34.31</span>
            <span class="EUR" style="display:none;">23.27&nbsp;€</span>
        </span>
    </span>
    <span style="display:none" class="raw_price">25.000</span>
</span>

AJAX调用返回单个HTML字符串,其中包含上述HTML的多个副本,价格各不相同。我想与正则表达式匹配的是:

  • 上述HTML的每个块(如上所述,它在返回字符串中多次出现)
  • 最外层name
  • span属性的值

到目前为止我所拥有的是:

var price_regex = new RegExp(/(<span([\s\S]*?)><span([\s\S]*?)>([\s\S]*?)<\/span><\/span\>)/gm);
console && console.log(price_regex.exec(product_price));

对于每次发生的价格中断,它都会匹配第一次价格中断(因此,如果name=1name=5name=15匹配name=1 3次。

我出错的行踪?

2 个答案:

答案 0 :(得分:2)

所以,如果你可以指望每个块中第一个跨度的格式,如下所示:

<span id="price_break_12345" name="1">

然后,你如何使用这样的代码循环所有匹配。此代码标识第一个范围中的price_break_xxxx id值,然后选择以下name属性:

var re = /id="price_break_\d+"\s+name="([^"]+)"/gm;
var match;
while (match = re.exec(str)) {
    console.log(match[1]);
}

你可以在这里看到它:http://jsfiddle.net/jfriend00/G39ne/

我使用转换器将三个HTML块放入一个javascript字符串中(以模拟从ajax调用中返回的内容),以便我可以在其上运行代码。


更有效的方法是使用浏览器的HTML解析器为您完成所有工作。假设你有一个名为`str'的字符串变量中的HTML,你可以像这样使用浏览器的解析器:

function getElementChildren(parent) {
    var elements = [];
    var children = parent.childNodes;
    for (var i = 0, len = children.length; i < len; i++) {
        // collect element nodes only
        if (children[i].nodeType == 1) {
            elements.push(children[i]);
        }
    }
    return(elements);
}

var div = document.createElement("div");
div.innerHTML = str;
var priceBlocks = getElementChildren(div);
for (i = 0; i < priceBlocks.length; i++) {
    console.log(priceBlocks[i].id + ", " + priceBlocks[i].getAttribute("name") + "<br>");
}

在这里演示:http://jsfiddle.net/jfriend00/F6D8d/

这将为您提供这些元素的所有DOM遍历函数,而不是在HTML上使用(有些脆弱的)正则表达式。

答案 1 :(得分:0)

在很大程度上感谢jfriend让我意识到为什么我的正则表达式以一种奇怪的方式匹配(while (price_break = regex.exec(string))而不是只执行一次),我已经有了它的工作:

var price_regex = new RegExp(/<span[\s\S]*?name="([0-9]+)"[\s\S]*?><span[\s\S]*?>[\s\S]*?<\/span><\/span\>/gm);
var price_break;
while (price_break = price_regex.exec(strProductPrice))
{
    console && console.log(price_break);
}

我有大量无用的()只是堵塞了结果集,所以剥离它们会让事情变得简单得多。

另一件事,如上所述,最初我只是在做

price_break = price_regex.exec(strProductPrice)

运行正则表达式一次,并仅返回第一个匹配(由于() s,我误认为返回了第一个匹配的3个副本)。通过循环遍历它们,它会继续评估正则表达式,直到所有匹配都已用完为止,我认为它正常运行,类似于PHP的preg_match