正規表現についてgcc 4.8以前のバグがありますか?


101

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

その上、たとえば2つの代替パターンしかない場合、正規表現はうまく機能します。たとえばst|mt、いくつかの理由で最後のパターンが一致しないようです。このコードはApple LLVMコンパイラーで適切に機能します。

問題を解決する方法についてのアイデアはありますか?

アップデートは、一つの可能な解決策は、例えば、複数の選択肢を実装するためにグループを使用することです(st|mt)|tr


9
はい、libstdc ++の<regex>サポートは不完全です。何をお手伝いしますか?
kennytm 2012

10
regexlibstdc ++のステータスについては、gcc.gnu.org
onlinedocs

51
真面目な話ですが、 "falseを返す"だけを行うregex_searchの実装を出荷することが良い考えだったのは誰ですか?「ああ、私たちはそれを文書化しました」というのは弱い反応のようです。
ポールルーベル

4
@ AK4749:これはエラーではありません。まったく実装されていません。この質問が現れる回数は驚くべきことですが、特に<regex>過去3〜4年間にlibstdc ++について何も変更されていないため(例:実装されていないまま)。
rubenvb 2012

5
@KeithThompson、それ<regex>gcc(コンパイラのフロントエンド)ではなくlibstdc ++(GCC標準ライブラリ)によって提供されることは事実ですが、GCC(プロジェクト)の一部です。「libstdc ++-v3はGCCの一部として開発およびリリースされています」を参照してください。ディストリビューションがGCCとは関係のない別のパッケージに分割することを選択した場合。
ジョナサンウェイクリー、2012年

回答:


168

<regex> GCC 4.9.0で実装およびリリースされました。

GCCの(古い)バージョンでは、実装されていません

そのプロトタイプ<regex>コードは、GCCのすべてのC ++ 0xサポートが非常に実験的で、初期のC ++ 0xドラフトを追跡し、人々が実験できるようになったときに追加されました。これにより、標準が完成する前に、問題を見つけて標準委員会にフィードバックを提供することができました。当時、C ++ 11が完成するずっと前に、そして他の多くのコンパイラがサポートを提供するずっと前に、最先端の機能にアクセスできたことに多くの人々が感謝し、そのフィードバックがC ++ 11の改善に本当に役立ちました。これはGood Thing TMでした。

この<regex>コードは決して有用な状態ではありませんでしたが、当時のコードの他の多くのビットと同様に、進行中の作業として追加されました。それはチェックインされ、最終的に完成することを意図して、必要に応じて他のユーザーが共同作業できるようになりました。

それがオープンソースの仕組みです:早期にリリースし、頻繁にリリースします -残念ながら<regex>、実装を終えたであろう多くの部分ではなく、初期の部分しか正しくない場合。

ライブラリのほとんどの部分はより完全で、現在はほぼ完全に実装され<regex>ていますが、実装されていなかったため、追加された後も同じ未完成の状態のままでした。

真面目な話ですが、 "falseを返す"だけを行うregex_searchの実装を出荷することが良い考えだったのは誰ですか?

数年前、C ++ 0xがまだ開発中で、部分的な実装を数多く出荷したのは、それほど悪い考えではありませんでした。だれもそれが長い間使用できないままであるとは思っていなかったので、後から考えて、それは無効にされ、それを有効にするためにマクロまたは組み込みオプションを必要としたはずです。しかし、その船はずっと前に出航した。regexコードに依存するlibstdc ++。soライブラリからエクスポートされたシンボルがあるため、単に(たとえば、GCC 4.8で)シンボルを削除するのは簡単ではありませんでした。


12

特徴検出

これは、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.tccています4.9.x
  • _GLIBCXX_REGEX_STATE_LIMIT定義さbits/regex_automatron.hています5+
  • _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開発者#define _GLIBCXX_HAVE_WORKING_REGEX 1が7.xリリースに永続化した(または何か、ヒントヒントナッジナッジ)を追加した場合、このスニペットはそれを含むように更新でき、以降のGCCリリースは上記のスニペットで動作します。

私の知る限りでは、他のすべてのコンパイラは、作業していたがYMMVを。<regex>__cplusplus >= 201103L

ヘッダーの外で_GLIBCXX_REGEX_DFS_QUANTIFIERS_LIMITまたは_GLIBCXX_REGEX_STATE_LIMITマクロを誰かが定義した場合、これは明らかに完全に壊れますstdc++-v3


非常に素晴らしい!GCC 4.9で新しくなったヘッダーの1つからヘッダーガードマクロをチェックすることをお勧めしましたが、ガードがありません:-\マクロはGCC 7では変更されていませんが、理論的にはGCCで実行できます8以上なので、gcc.gnu.org / bugzillaで機能拡張リクエストを提出_GLIBCXX_REGEX_IS_OK_NOW_KTHXBAIして、ヘッダーに何かを要求してください。忘れないようにしてください-ありがとう!
ジョナサンウェイクリー2016

1
@JonathanWakelyが78905を追加しました。それを拡張バグにする方法はわかりませんが、現在システムにあります。
Matt Clarkson、

1

現時点では(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で参照できます


1
「現時点では(g ++(GCC)4.9.2でstd = c ++ 14を使用)、まだregex_matchを受け入れていません。」それは真実ではありません、あなたはおそらくそれを間違って使用しています。
Jonathan Wakely 2017

1
あなたのコードは「regex_matchのように機能するアプローチ」ではありません。その関数は文字列全体ではなく、部分文字列を照合しようとするためですが、それでも間違って使用していると思います。あなたはそれでそれを行うことができstd::regex_searchます、wandbox.org / permlink / rLbGyYcYGNsBWsaBを
Jonathan Wakely
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.