Ist gcc 4.8 oder früher in Bezug auf reguläre Ausdrücke fehlerhaft?

Lesezeit: 9 Minuten

Ist gcc 48 oder fruher in Bezug auf regulare Ausdrucke
tunnuz

Ich versuche, std::regex in einem C++11-Code zu verwenden, aber es scheint, dass die Unterstützung etwas fehlerhaft ist. Ein Beispiel:

#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;
}

Ausgänge:

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

wenn mit gcc kompiliert (MacPorts gcc47 4.7.1_2) 4.7.1, entweder mit

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

oder

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

Außerdem funktioniert die Regex gut, wenn ich nur zwei alternative Muster habe, z st|mt, also sieht es so aus, als würde der letzte aus irgendwelchen Gründen nicht übereinstimmen. Der Code funktioniert gut mit dem Apple LLVM-Compiler.

Irgendwelche Ideen, wie man das Problem lösen kann?

Aktualisieren Eine mögliche Lösung besteht darin, Gruppen zu verwenden, um mehrere Alternativen zu implementieren, z (st|mt)|tr.

  • Ja, libstdc++ <regex> Unterstützung ist unvollständig. Was können wir Ihnen helfen?

    – kennytm

    21. September 2012 um 12:18 Uhr

  • Für den Stand von regex in libstdc++, siehe gcc.gnu.org/onlinedocs/libstdc++/manual/…

    – ekatmur

    21. September 2012 um 12:53 Uhr

  • Im Ernst, wer hätte gedacht, dass es eine gute Idee war, eine Implementierung von regex_search zu versenden, die nur “false” zurückgibt? “Oh, wir haben es dokumentiert” scheint eine schwache Antwort zu sein.

    – Paul Rubel

    21. September 2012 um 20:35 Uhr

  • @AK4749: Dies ist kein Fehler. Es ist einfach nicht implementiert. Obwohl die Häufigkeit, mit der diese Frage auftaucht, alarmierend ist, zumal sich an der libstdc++ nichts geändert hat <regex>in den letzten 3-4 Jahren (wie in: es bleibt nicht implementiert).

    – rubenvb

    21. September 2012 um 20:55 Uhr

  • @KeithThompson, obwohl das stimmt <regex> wird von libstdc++ (der GCC-Standardbibliothek) nicht bereitgestellt gcc (das Compiler-Frontend), es ist Teil von GCC (dem Projekt). Sehen “libstdc++-v3 wird als Teil von GCC entwickelt und veröffentlicht”. Wenn Ihre Distribution es in ein separates Paket aufteilt, hat das nichts mit GCC zu tun.

    – Jonathan Wakely

    1. Oktober 2012 um 14:44 Uhr


Ist gcc 48 oder fruher in Bezug auf regulare Ausdrucke
Jonathan Wakely

<regex> wurde in GCC 4.9.0 implementiert und veröffentlicht.

In Ihrer (älteren) Version von GCC ist dies der Fall nicht implementiert.

Dieser Prototyp <regex> Code wurde hinzugefügt, als die gesamte C++0x-Unterstützung von GCC vorhanden war höchst experimentell, verfolgt frühe C++0x-Entwürfe und wird Leuten zum Experimentieren zur Verfügung gestellt. Dadurch konnten die Leute Probleme finden und dem Standardausschuss Feedback geben, bevor der Standard fertiggestellt wurde. Zu dieser Zeit waren viele Leute dankbar dafür, dass sie Zugriff auf modernste Funktionen hatten, lange bevor C++11 fertig war und viele andere Compiler zur Verfügung standen irgendein Unterstützung, und dieses Feedback hat wirklich dazu beigetragen, C++11 zu verbessern. Das war eine gute SacheTM.

Die <regex> Code war nie in einem nützlichen Zustand, sondern wurde wie viele andere Code-Bits zu dieser Zeit als Work-in-Progress hinzugefügt. Es wurde eingecheckt und anderen zur Zusammenarbeit zur Verfügung gestellt, wenn sie wollten, mit der Absicht, dass es irgendwann fertig sein würde.

So funktioniert Open Source oft: Lassen Sie früh los, lassen Sie oft los — leider im Fall von <regex> Wir haben nur den frühen Teil richtig gemacht und nicht den häufigen Teil, der die Implementierung abgeschlossen hätte.

Die meisten Teile der Bibliothek wurden vollständiger und sind jetzt fast vollständig implementiert, aber <regex> war nicht, also blieb es in demselben unvollendeten Zustand, seit es hinzugefügt wurde.

Im Ernst, wer hätte gedacht, dass es eine gute Idee war, eine Implementierung von regex_search zu versenden, die nur “false” zurückgibt?

Vor ein paar Jahren war das keine so schlechte Idee, als C++0x noch in Arbeit war und wir viele Teilimplementierungen ausgeliefert haben. Niemand dachte, dass es so lange unbrauchbar bleiben würde, also hätte es im Nachhinein vielleicht deaktiviert werden sollen und ein Makro oder eine eingebaute Option benötigt, um es zu aktivieren. Aber dieses Schiff ist vor langer Zeit gesegelt. Es gibt exportierte Symbole aus der libstdc++.so Bibliothek, die vom Regex-Code abhängen, also wäre es nicht trivial gewesen, sie einfach zu entfernen (in, sagen wir, GCC 4.8).

1647274809 242 Ist gcc 48 oder fruher in Bezug auf regulare Ausdrucke
Matt Clarkson

Feature-Erkennung

Dies ist ein Ausschnitt, um zu erkennen, ob die libstdc++ Implementierung wird mit C-Präprozessor implementiert definiert:

#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

Makros

  • _GLIBCXX_REGEX_DFS_QUANTIFIERS_LIMIT ist definiert in bits/regex.tcc in 4.9.x
  • _GLIBCXX_REGEX_STATE_LIMIT ist definiert in bits/regex_automatron.h in 5+
  • _GLIBCXX_RELEASE wurde hinzugefügt 7+ als Ergebnis von diese Antwort und ist die GCC-Hauptversion

Testen

Sie können es mit GCC wie folgt testen:

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

Ergebnisse

Hier sind einige Ergebnisse für verschiedene Compiler:


$ 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

Hier sind Drachen

Dies wird völlig nicht unterstützt und beruht auf der Erkennung privater Makros, die die GCC-Entwickler in die eingefügt haben bits/regex* Kopfzeilen. Sie könnten sich ändern und weggehen Jederzeit. Hoffentlich werden sie in den aktuellen Versionen 4.9.x, 5.x, 6.x nicht entfernt, aber sie könnten in den 7.x-Versionen verschwinden.

Wenn die GCC-Entwickler a #define _GLIBCXX_HAVE_WORKING_REGEX 1 (oder so ähnlich, hint hint nudge nudge) in der 7.x-Version, die fortbesteht, könnte dieses Snippet aktualisiert werden, um dies einzuschließen, und spätere GCC-Versionen würden mit dem obigen Snippet funktionieren.

Soweit ich weiß, funktionieren alle anderen Compiler <regex> wann __cplusplus >= 201103L aber YMMV.

Offensichtlich würde dies vollständig brechen, wenn jemand das definiert _GLIBCXX_REGEX_DFS_QUANTIFIERS_LIMIT oder _GLIBCXX_REGEX_STATE_LIMIT Makros außerhalb der stdc++-v3 Kopfzeilen.

  • Sehr schön! Ich wollte vorschlagen, nach dem Header Guard-Makro von einem der Header zu suchen, der neu in GCC 4.9 ist, aber sie haben keine Guards :-\ Die Makros ändern sich nicht für GCC 7, aber theoretisch könnten sie es für GCC tun 8+, reichen Sie also bitte eine Verbesserungsanfrage ein unter gcc.gnu.org/bugzilla nach etwas fragen wie _GLIBCXX_REGEX_IS_OK_NOW_KTHXBAI in den Headern, damit es nicht vergessen wird – danke!

    – Jonathan Wakely

    16. Dezember 2016 um 18:06 Uhr


  • @JonathanWakely haben hinzugefügt 78905. Ich bin mir nicht sicher, wie ich das zu einem Verbesserungsfehler machen soll, aber es ist jetzt im System.

    – Matt Clarkson

    22. Dezember 2016 um 17:40 Uhr

1647274809 169 Ist gcc 48 oder fruher in Bezug auf regulare Ausdrucke
Luis Orantes

In diesem Moment (unter Verwendung von std=c++14 in g++ (GCC) 4.9.2) wird regex_match immer noch nicht akzeptiert.

Hier ist ein Ansatz, der wie regex_match funktioniert, aber stattdessen sregex_token_iterator verwendet. Und es funktioniert mit 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;

es wird 1 2 3 gedruckt

Sie können die sregex_token_iterator-Referenz lesen in:
http://en.cppreference.com/w/cpp/regex/regex_token_iterator

  • “Zu diesem Zeitpunkt (unter Verwendung von std=c++14 in g++ (GCC) 4.9.2) wird regex_match immer noch nicht akzeptiert.” Das ist nicht wahr, du verwendest es wahrscheinlich falsch.

    – Jonathan Wakely

    29. September 2017 um 11:45 Uhr

  • Ihr Code ist kein “Ansatz, der wie regex_match funktioniert”, da diese Funktion versucht, Teilzeichenfolgen abzugleichen, nicht die gesamte Zeichenfolge, daher denke ich immer noch, dass Sie sie falsch verwenden. Du kannst es mit machen std::regex_search obwohl, siehe wandbox.org/permlink/rLbGyYcYGNsBWsaB

    – Jonathan Wakely

    29. September 2017 um 11:58 Uhr


1002330cookie-checkIst gcc 4.8 oder früher in Bezug auf reguläre Ausdrücke fehlerhaft?

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy