簡體   English   中英

gcc 4.8 或更早版本是否有關於正則表達式的錯誤?

[英]Is gcc 4.8 or earlier buggy about regular expressions?

我試圖在一段 C++11 代碼中使用 std::regex,但似乎支持有點問題。 一個例子:

#include <regex>
#include <iostream>

int main (int argc, const char * argv[]) {
    std::regex r("st|mt|tr");
    std::cerr << "st|mt|tr" << " matches st? " << std::regex_match("st", r) << std::endl;
    std::cerr << "st|mt|tr" << " matches mt? " << std::regex_match("mt", r) << std::endl;
    std::cerr << "st|mt|tr" << " matches tr? " << std::regex_match("tr", r) << std::endl;
}

輸出:

st|mt|tr matches st? 1
st|mt|tr matches mt? 1
st|mt|tr matches tr? 0

當使用 gcc (MacPorts gcc47 4.7.1_2) 4.7.1 編譯時,要么使用

g++ *.cc -o test -std=c++11
g++ *.cc -o test -std=c++0x

或者

g++ *.cc -o test -std=gnu++0x

此外,如果我只有兩種替代模式,例如st|mt ,則正則表達式效果很好,因此由於某些原因,看起來最后一個不匹配。 該代碼適用於 Apple LLVM 編譯器。

關於如何解決問題的任何想法?

更新一種可能的解決方案是使用組來實現多個替代方案,例如(st|mt)|tr

<regex>在 GCC 4.9.0 中實現和發布。

在您(舊)版本的 GCC 中,它沒有實現

當 GCC 的所有 C++0x 支持都處於高度實驗性、跟蹤早期 C++0x 草案並可供人們進行實驗時,添加了該原型<regex>代碼。 這允許人們在標准最終確定之前發現問題並向標准委員會提供反饋。 當時,很多人都慶幸在 C++11 完成之前以及許多其他編譯器提供任何支持之前就可以使用最前沿的特性,而這種反饋確實有助於改進 C++11。 這是一件好事TM

<regex>代碼從未處於有用狀態,而是像當時的許多其他代碼一樣作為正在進行的工作添加。 它被簽入並提供給其他人,如果他們願意,可以進行協作,目的是最終完成。

這通常是開源的工作方式:早發布,經常發布——不幸的是,在<regex>的情況下,我們只得到了早期的部分,而不是完成實施的經常部分。

庫的大部分內容更加完整,現在幾乎完全實現,但<regex>沒有實現,所以它自添加以來一直處於未完成狀態。

不過說真的,誰認為發布一個只執行“返回假”的 regex_search 實現是個好主意?

幾年前,這並不是一個壞主意,當時 C++0x 仍在開發中,我們發布了許多部分實現。 沒有人認為它會長時間無法使用,所以事后看來,也許它應該被禁用並需要一個宏或內置時間選項來啟用它。 但那艘船很久以前就航行了。 libstdc++.so庫中的導出符號依賴於正則表達式代碼,因此簡單地將其刪除(例如,在 GCC 4.8 中)並非易事。

特征檢測

這是一個片段,用於檢測libstdc++實現是否使用 C 預處理器定義:

#include <regex>
#if __cplusplus >= 201103L &&                             \
    (!defined(__GLIBCXX__) || (__cplusplus >= 201402L) || \
        (defined(_GLIBCXX_REGEX_DFS_QUANTIFIERS_LIMIT) || \
         defined(_GLIBCXX_REGEX_STATE_LIMIT)           || \
             (defined(_GLIBCXX_RELEASE)                && \
             _GLIBCXX_RELEASE > 4)))
#define HAVE_WORKING_REGEX 1
#else
#define HAVE_WORKING_REGEX 0
#endif

  • _GLIBCXX_REGEX_DFS_QUANTIFIERS_LIMIT定義bits/regex.tcc4.9.x
  • _GLIBCXX_REGEX_STATE_LIMIT5+中的bits/regex_automatron.h定義
  • 由於此答案_GLIBCXX_RELEASE已添加到7+並且是 GCC 主要版本

測試

你可以像這樣用 GCC 測試它:

cat << EOF | g++ --std=c++11 -x c++ - && ./a.out
#include <regex>

#if __cplusplus >= 201103L &&                             \
    (!defined(__GLIBCXX__) || (__cplusplus >= 201402L) || \
        (defined(_GLIBCXX_REGEX_DFS_QUANTIFIERS_LIMIT) || \
         defined(_GLIBCXX_REGEX_STATE_LIMIT)           || \
             (defined(_GLIBCXX_RELEASE)                && \
             _GLIBCXX_RELEASE > 4)))
#define HAVE_WORKING_REGEX 1
#else
#define HAVE_WORKING_REGEX 0
#endif

#include <iostream>

int main() {
  const std::regex regex(".*");
  const std::string string = "This should match!";
  const auto result = std::regex_search(string, regex);
#if HAVE_WORKING_REGEX
  std::cerr << "<regex> works, look: " << std::boolalpha << result << std::endl;
#else
  std::cerr << "<regex> doesn't work, look: " << std::boolalpha << result << std::endl;
#endif
  return result ? EXIT_SUCCESS : EXIT_FAILURE;
}
EOF

結果

以下是各種編譯器的一些結果:


$ gcc --version
gcc (GCC) 4.8.5 20150623 (Red Hat 4.8.5-11)
Copyright (C) 2015 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

$ ./a.out
<regex> doesn't work, look: false

$ gcc --version
gcc (GCC) 6.2.1 20160830
Copyright (C) 2016 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

$ ./a.out
<regex> works, look: true

$ gcc --version
gcc (Debian 4.9.2-10) 4.9.2
Copyright (C) 2014 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

$ ./a.out
<regex> works, look: true

$ gcc --version
gcc (Ubuntu 6.2.0-5ubuntu12) 6.2.0 20161005
Copyright (C) 2016 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

$ ./a.out
<regex> works, look: true

$ gcc --version
gcc (Ubuntu 5.4.0-6ubuntu1~16.04.4) 5.4.0 20160609
Copyright (C) 2015 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

$ ./a.out
<regex> works, look: true

$ gcc --version
gcc (GCC) 6.2.1 20160830
Copyright (C) 2016 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

$ clang --version
clang version 3.9.0 (tags/RELEASE_390/final)
Target: x86_64-unknown-linux-gnu
Thread model: posix
InstalledDir: /usr/bin
$ ./a.out  # compiled with 'clang -lstdc++'
<regex> works, look: true

這里是龍

這是完全不受支持的,並且依賴於檢測 GCC 開發人員放入bits/regex*標頭中的私有宏。 他們可以改變和消失隨時 希望它們不會在當前的 4.9.x、5.x、6.x 版本中被刪除,但它們可能會在 7.x 版本中消失。

如果 GCC 開發人員在持續存在的 7.x 版本中添加了#define _GLIBCXX_HAVE_WORKING_REGEX 1 (或其他東西,提示提示輕推輕推),則可以更新此代碼段以包含該代碼段,並且以后的 GCC 版本將與上述代碼段一起使用。

據我所知,當__cplusplus >= 201103L但 YMMV 時,所有其他編譯器都有一個有效的<regex>

顯然,如果有人在stdc++-v3標頭之外定義了_GLIBCXX_REGEX_DFS_QUANTIFIERS_LIMIT_GLIBCXX_REGEX_STATE_LIMIT宏,這將完全中斷。

此時(在 g++ (GCC) 4.9.2 中使用 std=c++14)仍然不接受 regex_match。

這是一種類似於 regex_match 但使用 sregex_token_iterator 的方法。 它適用於 g++。

string line="1a2b3c";
std::regex re("(\\d)");
std::vector<std::string> inVector{
    std::sregex_token_iterator(line.begin(), line.end(), re, 1), {}
};

//prints all matches
for(int i=0; i<inVector.size(); ++i)
    std::cout << i << ":" << inVector[i] << endl;

它將打印 1 2 3

您可以在以下位置閱讀 sregex_token_iterator 參考: http ://en.cppreference.com/w/cpp/regex/regex_token_iterator

暫無
暫無

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

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