Regex frage
-
Meine Frage: Habe ich etwas im C++-Standard nicht verstanden oder liegen Fehler der Compiler vor? Zur Erläuterung:
Die regulären Ausdrücke sollen in C++ laut C++Standard entsprechend dem ECMA-262-Standard behandelt werden. Ich habe jedoch beobachtet, dass das möglicherweise für g++ und clang++ nicht stimmt. Das folgende Testprogramm vergleicht boost::regex mit std::regex. Dabei liefert boost::regex meiner Meinung nach in jedem Fall das richtige Ergebnis.
#include <boost/regex.hpp> #include <fstream> #include <iostream> #include <regex> #include <string> int main(int argc, char *argv[]) { std::string teststring = "text\na new line"; std::string searched_for[]{"\\n", "(\\n)", "(\\n)"}; std::string replacement[]{"\\n\\n", "\\1\\1", "$1$1"}; std::string headers[] = {"parsing escape", "backreference \\d:", "backreference $"}; for (unsigned int testcase = 0; testcase < 3; ++testcase) { boost::regex boost_searched_for(searched_for[testcase]); std::string boostresult = boost::regex_replace( teststring, boost_searched_for, replacement[testcase]); std::cout << '\n' << headers[testcase] << "\nboost-regex:\n" << boostresult << '\n'; std::regex std_searched_for(searched_for[testcase]); std::string stdresult = std::regex_replace( teststring, std_searched_for, replacement[testcase]); std::cout << "std-regex:\n" << stdresult << '\n'; } }
In den ersten beiden Testfällen stimmen die Ergebnisse nicht überein. Es stellt sichheraus, dass die Implementation von std::regex bei g++ und clang++ in den ersten beiden Fällen ein anderes Ergebnis als boost::regex liefert.
std::regex interpretiert \n als literale Zeichen \ und n. boost::regex interpretiert sie richtig, entsprechend ECMA 21.2.2.10 CharacterEscape
(Quelle: http://www.ecma-international.org/publications/files/ECMA-ST/Ecma-262.pdf, Stand Mai 2016)21.2.3.1 sagt bzgl des RegExp Konstruktors:
"If pattern is supplied using a StringLiteral, the usual escape sequence substitutions are performed before the String is processed by RegExp"Auch Capturing Groups und Rückreferenzen werden nur von boost::regex richtig behandelt (Testfall 2), d.h. ein LF (line feed) wird durch zwei LFs ersetzt. ECMA-262 lautet am Ende von 21.2.2.1:
"An EscapeValue is either a character or an integer. An EscapeValue is used to denote the interpretation of a DecimalEscape escape sequence: a character ch means that the escape sequence is interpreted as the character ch, while an integer n means that the escape sequence is interpreted as a backreference to the nth set of capturing parentheses."
Nur die nach ECMA-262 ebenfalls erlaubten Rückreferenzen mit dem $-Zeichen werden in beiden Fällen richtig behandelt (Testfall 3).
Habe ich etwas im C++- oder ECMA_Standard nicht verstanden oder liegen fehler der Compiler vor?
(benutzt wurde g++ 6.1 und clang++4.0 (svn) mit -std++=c++14)