正则表达式如何不匹配其他标记内的整个嵌套标记

时间:2017-07-26 14:24:04

标签: r regex

如何匹配内部(或外部,如果它更容易)只跨度标记?

<br><br><span class="header3">Statistical Analysis 1 for Percent Change From Baseline in the <span class="hit_inf">Psoriasis</span> Area Severity Index (PASI) Score at Week 16</span>

我正在尝试:(?:<span).*?(<span).*?(?:</span>).*</span>但只有第二个<span在单独的群组中匹配。我只需要使用span关键字。有什么建议吗?

1 个答案:

答案 0 :(得分:0)

你应该从不使用正则表达式匹配嵌套模式,如括号或示例XML标记。 问题在于,在所有语言中,正则表达式(除了两个或三个)都不能与嵌套的东西匹配。

示例:

正则表达式:/<span class="awesome">.*<\/span>/

匹配:<span> <span class="awesome">text</span></span>

正则表达式:/<span class="awesome">.*?<\/span>/

匹配: <span class="awesome"><span>text</span> </span>

解决方案:

有一些解决方案可以正确处理xml / html数据。第一个是使用 xml库。相当多的高级语言都有相当不错的xml库 - 只需使用一个。 对于调试和快速和肮脏解决方案,您也可以拆分内容并自行分析。

因为我的R技能非常糟糕,这是一个简单的JS解决方案:

&#13;
&#13;
// simple xml string
var text = '<br/><br/><span class="header3">Statistical Analysis 1 for Percent Change From Baseline in the <span class="hit_inf">Psoriasis</span> Area Severity Index (PASI) Score at Week 16</span>'

// split the string
var parts = text.split(/(<\/?)(.*?)(\/?>)/);

// predefine some vars
var level = 0;
var path = ["!ROOT!"]
var isOpen = false;
var isTag = false;

// go trough all parts
parts.forEach((match, index, all) => {
    // ignore empty stuff
    if (!match) return;

    // check type of match
    switch (match) {
        case "<":
            level++;
            isOpen = true;
            isTag = true;
            break;
        case "</":
            level--;
            isOpen = false;
            isTag = true;
            break;
        case ">":
            // add to path if open, otherwise remove last one from path
            if (isOpen) {
                path.push(all[index - 1]);
            } else {
                path.pop()   
            }
            isTag = false;
            break;
        case "/>":
            level --;
            isTag = false;
            break;
        default:
            // just print it out
            if (isTag) {
                console.log(new Array(level + (isOpen ? 0 : 1)).join("  "), "[TAG]", isOpen ? "[OPEN]" : "[CLOSE]", match);    
            } else {
                console.log(new Array(level + 1).join("  "), "[TEXT]", match);    
            }
    }
});
&#13;
&#13;
&#13;