簡體   English   中英

捕獲組標准 C++ RegEx 和 PCRE 中只有 1 個匹配項

[英]Only 1 match in capture groups standard C++ RegEx and PCRE

我有一個似乎無法解決的大問題,我正在嘗試解析由 C++ 中的 uWebSockets 檢索到的表單數據。

我決定為此使用正則表達式。 C++ 標准 function不起作用,運行大約需要 5 分鍾。

嘗試了多種語言之后,在我看來問題出在 C++ (或 JavaScript )不允許在捕獲組中進行回溯,因為它在任何其他語言中都可以正常工作。

切換到 PCRE 允許進行 1 次匹配(並且檢索結果的速度提高了大約 10 倍),但 rest 仍然是空的。

您可以看到PCRE(v2 和 v1)按預期工作

這是一個很好地描述問題的例子:

#include <pcrecpp.h>
#include <iostream>

int main() {
    std::string contents = "--------------------------eba4d02620bdb4f6\nContent-Disposition: form-data; name=\"ZIP\"; filename=\"h.png\"\nContent-Type: image/png\n\n--------------------------8c078fed966ff6fe\nContent-Disposition: form-data; name=\"ZIP\"; filename=\"tree-pack.xml\"\nContent-Type: application/xml\n\n<?xml version=\"1.0\"?>\n<Packages>\n  <Individual name=\"Designer\">\n    <Name>Designer</Name>\n    <Description>A BrAIn-API add-on that adds routes to help people design. This makes routes to generate colour palettes, generates fonts and even send previews of those to show how they look.</Description>\n    <ID></ID>\n    <FilePath>/packages/ID</FilePath>\n  </Individual>\n</Packages>\n\n--------------------------8c078fed966ff6fe--\n\n--------------------------eba4d02620bdb4f6--\n";
    pcrecpp::RE reg("-+.+\\nContent-Disposition: form-data; name=\"(\\w+| +)\"; filename=\"(.+)\"\\nContent-Type: (\\w+\\/\\w+)\\n\\n((.|\\n)+)\\n-+.+--.+|\\n+", pcrecpp::RE_Options()
    .set_caseless(true)
    .set_multiline(true));
    pcrecpp::StringPiece input(contents);
    int count = 0;
    std::string match;

    std::cout << contents << std::endl;

    while (reg.FindAndConsume(&input, &match)) { //This while loop makes sure that it only logs the amount of matches it is able to find; giving it a defined amount of matches it needs to find has the same output.
        count++;
        std::cout << count << " " << match << std::endl;
    }
}

我在 Ubuntu 20.04 上使用g++ file.cpp -o file -lpcrecpp運行它。output 對我來說是:

 Content-Disposition: form-data; name="ZIP"; filename="h.png" Content-Type: image/png --------------------------8c078fed966ff6fe Content-Disposition: form-data; name="ZIP"; filename="tree-pack.xml" Content-Type: application/xml <?xml version="1.0"?> <Packages> <Individual name="Designer"> <Name>Designer</Name> <Description>A BrAIn-API add-on that adds routes to help people design. This makes routes to generate colour palettes, generates fonts and even send previews of those to show how they look.</Description> <ID></ID> <FilePath>/packages/ID</FilePath> </Individual> </Packages> --------------------------8c078fed966ff6fe-- --------------------------eba4d02620bdb4f6-- 1 ZIP 2

如果您對已經解析 formdata 或任何內容的庫有任何建議,我也很想聽聽。

感謝您的閱讀,並提前感謝我能得到的任何和所有幫助!

在您的鏈接中,該模式似乎與您的示例代碼一樣失敗。 因此,我更改了您的模式以使其正常工作,並為清楚起見更改了while ()

通過這些更改(見下文),我現在找到了兩個匹配項:

1 Content-Disposition: form-data; ZIP h.png
2 Content-Disposition: form-data; ZIP tree-pack.xml
  • 我在(Content-Disposition: form-data;)周圍添加了一個組以供以后使用。
  • 在“Content-Type:”之后,我從(.|\\n)+更改為非貪婪(.|\\n)+? .
  • 我刪除了\\n-+.+--.+|\\n+以替換為第一組的負前瞻: (?!\1)
  • 出於演示目的,我將match更改為match[1-3]

你有一個貪婪地吞噬所有未來模式的模式

#include <pcrecpp.h>
#include <iostream>

int main() {
    std::string contents = "--------------------------eba4d02620bdb4f6\nContent-Disposition: form-data; name=\"ZIP\"; filename=\"h.png\"\nContent-Type: image/png\n\n--------------------------8c078fed966ff6fe\nContent-Disposition: form-data; name=\"ZIP\"; filename=\"tree-pack.xml\"\nContent-Type: application/xml\n\n<?xml version=\"1.0\"?>\n<Packages>\n  <Individual name=\"Designer\">\n    <Name>Designer</Name>\n    <Description>A BrAIn-API add-on that adds routes to help people design. This makes routes to generate colour palettes, generates fonts and even send previews of those to show how they look.</Description>\n    <ID></ID>\n    <FilePath>/packages/ID</FilePath>\n  </Individual>\n</Packages>\n\n--------------------------8c078fed966ff6fe--\n\n--------------------------eba4d02620bdb4f6--\n";
    pcrecpp::RE reg("-+.+\\n(Content-Disposition: form-data;) name=\"(\\w+| +)\"; filename=\"(.+)\"\\nContent-Type: (\\w+\\/\\w+)\\n\\n((.|\\n)+?)(?!\1)", pcrecpp::RE_Options()
    .set_caseless(true)
    .set_multiline(true));
    pcrecpp::StringPiece input(contents);
    int count = 0;
    std::string match1, match2, match3;

    std::cout << contents << std::endl;

    while (reg.FindAndConsume(&input, &match1, &match2, &match3)) {
        count++;
        std::cout << count << " " << match1
            << " " << match2 << " " << match3 << std::endl;
    }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM