2014-03-18 55 views
3

我想通过使用正则表达式从QString(.html)中提取信息。我明确地想要使用正则表达式(无解析器解决方案)和类QRegularExpression(出于若干原因,例如:Reasons)。QT C++ QRegularExpression多个匹配

为简化方面,这里是一个问题的等价任务。

构筑源字符串:

<foo><bar s>INFO1.1</bar> </ qux> <peter></peter><bar e>INFO1.2 
</bar><fred></ senseless></fred></ xx><lol></lol></foo><bar s>INFO2.1</bar> 
</ nothing><endlessSenselessTags></endlessSenselessTags><rofl> 
<bar e>INFO2.2</bar></rofl> 

*注:*可能会有或多或少的相关信息和附加sensless标签。 (6相关信息例如)

寻求:

Info1.1和Info1.2和Info2.1和Info2.2(例如,在列表)

尝试

1.

QRegularExpression reA(".*<bar [es]>(.*)</bar>.*", QRegularExpression::DotMatchesEverythingOption); 

- >

INFOa</bar> </ qux> <peter></peter><bar e>INFOb 
    </bar><fred></ senseless></fred></ xx><lol></lol></foo><bar s>INFOc</bar> 
    </ nothing><endlessSenselessTags></endlessSenselessTags><rofl> 
    <bar e>INFOd 

2.

QRegularExpression reA("(.*<bar [es]>(.*)</bar>.*)*", QRegularExpression::DotMatchesEverythingOption); 

- >无谓

问题: 正则表达式总是与整个字符串。 <bar s>INFO</bar><bar s>INFO</bar>会选择第一个<bar s>,最后一个和</bar>。通缉是第一

与QRegExp似乎有一个解决方案,但我想用QRegularExpression做到这一点。

+0

简单:你不使用HTML/XML的正则表达式。您应该使用DOM库。至于你的正则表达式,它正在执行它通常的贪婪匹配,所以它会匹配你的整个字符串中的FIRST'bar'和LAST'bar'。 –

回答

4

也许你可以用这个

QRegularExpression reA("(<bar [se]>[^<]+</bar>)"); 

QRegularExpressionMatchIterator i = reA.globalMatch(input); 
while (i.hasNext()) { 
    QRegularExpressionMatch match = i.next(); 
    if (match.hasMatch()) { 
     qDebug() << match.captured(0); 
    } 
} 

尝试,让我这个输出

"<bar s>INFO1.1</bar>" 
"<bar e>INFO1.2 
</bar>" 
"<bar s>INFO2.1</bar>" 
"<bar e>INFO2.2</bar>" 

,而这种表达

QRegularExpression reA("((?<=<bar [se]>)((?!</bar>).)+(?=</bar>))", 
         QRegularExpression::DotMatchesEverythingOption); 

与该输入

<foo><bar s>INFO1</lol>.1</bar> </ qux> <peter></peter><bar e>INFO1.2 
</bar><fred></ senseless></fred></ xx><lol></lol></foo><bar s>INFO2.1</bar> 
</ nothing><endlessSenselessTags></endlessSenselessTags><rofl> 
<bar e>INFO2.2</bar></rofl> 

给了我作为输出

"INFO1</lol>.1" 
"INFO1.2 
" 
"INFO2.1" 
"INFO2.2" 
+0

谢谢,QRegularExpressionMatchIterator和globalMatch是我期待的。但是如果“INFO1.1”也可以包含“<”(另一个标签),你会怎么做。例如“Info < /lol> 1.1”。我试图使用“(?!表达式)”运算符,但这似乎不起作用。我试过'(?!)。+)'。想要:“ INFO1.1”,“ INFO1.2”等? – SearchSpace

+0

@ user3434345:我编辑过。你在这。 –

1

我加入一个新的类似的答案,由于伤脑筋缺乏QRegularExpression答案是处理所有指定的捕捉组,而不是按名称。我只是希望能够指定捕获组,并只获得这些结果,而不是整个厨房水槽。当盲目抓取捕获组0时,这成为一个问题,这是几乎所有SO的答案都会对多个结果产生QRegularExpression。这个答案取回列表中的所有指定捕获组,并且如果没有指定捕获组,则它返回整个正则表达式匹配的捕获组0。

我在Gist上做了this simplified code-snippet,并没有直接解决这个问题。下面的示例应用程序如果差异确实解决了这个特定的问题。

#include <QCoreApplication> 
#include <QRegularExpressionMatch> 
#include <QStringList> 
#include <iostream> 
int main(int argc, char *argv[]) 
{ 
    QCoreApplication a(argc, argv); 

    QStringList results; 
    QRegularExpression this_regex("<bar \\w>(.*?)</bar>"); 
    QString test_string = "<foo><bar s>INFO1.1</bar> </ qux> <peter></peter><bar e>INFO1.2\n\ 
          </bar><fred></ senseless></fred></ xx><lol></lol></foo><bar s>INFO2.1</bar>\n\ 
          </ nothing><endlessSenselessTags></endlessSenselessTags><rofl>\n\ 
          <bar e>INFO2.2</bar></rofl>\n"; 

    if(!this_regex.isValid()) 
    { 
     std::cerr << "Invalid regex pattern: " << this_regex.pattern().toStdString() << std::endl; 
     return -2; 
    } 

    for (int i = 0; i < this_regex.captureCount()+1; ++i) 
    { 
     // This skips storing capture-group 0 if any capture-groups were actually specified. 
     // If they weren't, capture-group 0 will be the only thing returned.  
     if((i!=0) || this_regex.captureCount() < 1) 
     { 
      QRegularExpressionMatchIterator iterator = this_regex.globalMatch(test_string);  
      while (iterator.hasNext()) 
      { 
       QRegularExpressionMatch match = iterator.next();  
       QString matched = match.captured(i);  
       // Remove this if-check if you want to keep zero-length results 
       if(matched.length() > 0){results << matched;} 
      } 
     } 
    } 

    if(results.length()==0){return -1;} 

    for(int i = 0; i < results.length(); i++) 
    { 
     std::cout << results.at(i).toStdString() << std::endl; 
    } 

    return 0; 
} 

输出控制台:

INFO1.1 
INFO2.1 
INFO2.2 

对我来说,处理使用QRegularExpression正则表达式比std::regex的痛苦少,但他们都相当普遍的和强大的,需要更多的细调整结果处理。我总是使用我为QRegularExpression s制作的包装来快速制作我通常想要利用的那种正则表达式和结果。