¿Gcc 4.8 o versiones anteriores tienen errores con respecto a las expresiones regulares?

9 minutos de lectura

¿Gcc 48 o versiones anteriores tienen errores con respecto a
Tunnuz

Estoy tratando de usar std::regex en un código de C++ 11, pero parece que el soporte tiene algunos errores. Un ejemplo:

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

salidas:

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

cuando se compila con gcc (MacPorts gcc47 4.7.1_2) 4.7.1, ya sea con

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

o

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

Además, la expresión regular funciona bien si solo tengo dos patrones alternativos, por ejemplo st|mt, por lo que parece que el último no coincide por alguna razón. El código funciona bien con el compilador LLVM de Apple.

¿Alguna idea sobre cómo resolver el problema?

Actualizar una posible solución es usar grupos para implementar múltiples alternativas, por ejemplo (st|mt)|tr.

  • Sí libstdc++ <regex> el soporte es incompleto. ¿En qué podemos ayudarte?

    – kennytm

    21 de septiembre de 2012 a las 12:18

  • Por el estado de regex en libstdc++, consulte gcc.gnu.org/onlinedocs/libstdc++/manual/…

    – ecatmur

    21 de septiembre de 2012 a las 12:53

  • Hablando en serio, ¿quién pensó que enviar una implementación de regex_search que solo “devuelve falso” era una buena idea? “Oh, lo documentamos” parece una respuesta débil.

    – Pablo Rubel

    21/09/2012 a las 20:35

  • @ AK4749: esto no es un error. Simplemente no está implementado. Aunque la cantidad de veces que aparece esta pregunta es alarmante, especialmente porque nada cambió en libstdc++ <regex>en los últimos 3-4 años (como en: sigue sin implementarse).

    – rubenvb

    21/09/2012 a las 20:55

  • @KeithThompson, si bien es cierto que <regex> es proporcionado por libstdc++ (la biblioteca estándar de GCC) no gcc (la interfaz del compilador), es parte de GCC (el proyecto). Ver “libstdc++-v3 se desarrolla y lanza como parte de GCC”. Si su distribución elige dividirlo en un paquete separado, eso no tiene nada que ver con GCC.

    –Jonathan Wakely

    1 oct 2012 a las 14:44


¿Gcc 48 o versiones anteriores tienen errores con respecto a
jonathan wakely

<regex> fue implementado y lanzado en GCC 4.9.0.

En su versión (más antigua) de GCC, es no se ha implementado.

ese prototipo <regex> el código se agregó cuando todo el soporte de C++0x de GCC estaba muy experimental, rastreando los primeros borradores de C++0x y poniéndolo a disposición de las personas para que experimenten. Eso permitió a las personas encontrar problemas y dar su opinión al comité de estándares antes de que se finalizara el estándar. En ese momento, muchas personas estaban agradecidas de haber tenido acceso a funciones de última generación mucho antes de que se terminara C++ 11 y antes de que se proporcionaran muchos otros compiladores. ninguna soporte, y esa retroalimentación realmente ayudó a mejorar C++11. Fue algo buenoTM.

los <regex> El código nunca estuvo en un estado útil, pero se agregó como un trabajo en progreso como muchos otros fragmentos de código en ese momento. Se registró y se puso a disposición de otros para que colaboraran si así lo deseaban, con la intención de que eventualmente se terminara.

A menudo, así es como funciona el código abierto: Libertad anticipada, la liberación a menudo — lamentablemente en el caso de <regex> solo acertamos en la primera parte y no en la parte frecuente que habría terminado la implementación.

La mayoría de las partes de la biblioteca eran más completas y ahora están casi completamente implementadas, pero <regex> no lo había estado, por lo que permaneció en el mismo estado sin terminar desde que se agregó.

Hablando en serio, ¿quién pensó que enviar una implementación de regex_search que solo “devuelve falso” era una buena idea?

No fue tan mala idea hace algunos años, cuando C++0x todavía era un trabajo en progreso y enviamos muchas implementaciones parciales. Nadie pensó que permanecería inutilizable durante tanto tiempo, por lo que, en retrospectiva, tal vez debería haberse deshabilitado y requerir una macro o una opción de tiempo integrado para habilitarlo. Pero ese barco zarpó hace mucho tiempo. Hay símbolos exportados desde el libstdc++.so biblioteca que depende del código regex, por lo que simplemente eliminarlo (en, por ejemplo, GCC 4.8) no habría sido trivial.

1647629409 994 ¿Gcc 48 o versiones anteriores tienen errores con respecto a
matt clarkson

Detección de características

Este es un fragmento para detectar si el libstdc++ la implementación se implementa con el preprocesador C define:

#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

macros

  • _GLIBCXX_REGEX_DFS_QUANTIFIERS_LIMIT es definido en bits/regex.tcc en 4.9.x
  • _GLIBCXX_REGEX_STATE_LIMIT es definido en bits/regex_automatron.h en 5+
  • _GLIBCXX_RELEASE fue añadido a 7+ como resultado de esta respuesta y es la versión principal de GCC

Pruebas

Puedes probarlo con GCC así:

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

Resultados

Aquí hay algunos resultados para varios compiladores:


$ 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

Aquí hay dragones

Esto no es totalmente compatible y se basa en la detección de macros privadas que los desarrolladores de GCC han puesto en el bits/regex* encabezados Podrían cambiar y desaparecer en cualquier momento. Con suerte, no se eliminarán en las versiones actuales 4.9.x, 5.x, 6.x, pero podrían desaparecer en las versiones 7.x.

Si los desarrolladores de GCC añadieran un #define _GLIBCXX_HAVE_WORKING_REGEX 1 (o algo así, sugerencia, sugerencia, empujón, empujón) en la versión 7.x que persistió, este fragmento podría actualizarse para incluir eso y las versiones posteriores de GCC funcionarían con el fragmento anterior.

Hasta donde yo sé, todos los demás compiladores tienen un trabajo <regex> Cuándo __cplusplus >= 201103L pero YMMV.

Obviamente, esto se rompería por completo si alguien definiera el _GLIBCXX_REGEX_DFS_QUANTIFIERS_LIMIT o _GLIBCXX_REGEX_STATE_LIMIT macros fuera del stdc++-v3 encabezados

  • ¡Muy agradable! Iba a sugerir verificar la macro de protección de encabezado de uno de los encabezados que es nuevo en GCC 4.9, pero no tienen protecciones :-\ Las macros no cambian para GCC 7, pero teóricamente podrían hacerlo para GCC 8+, así que presente una solicitud de mejora en gcc.gnu.org/bugzilla pidiendo algo como _GLIBCXX_REGEX_IS_OK_NOW_KTHXBAI en los encabezados, para que no se olvide – ¡gracias!

    –Jonathan Wakely

    16 dic 2016 a las 18:06


  • @JonathanWakely ha agregado 78905. No estoy seguro de cómo convertir eso en un error de mejora, pero ahora está en el sistema.

    –Matt Clarkson

    22 dic 2016 a las 17:40

1647629410 391 ¿Gcc 48 o versiones anteriores tienen errores con respecto a
Luis Orantes

En este momento (usando std=c++14 en g++ (GCC) 4.9.2) todavía no acepta regex_match.

Aquí hay un enfoque que funciona como regex_match pero usando sregex_token_iterator en su lugar. Y funciona con 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;

imprimirá 1 2 3

puede leer la referencia sregex_token_iterator en:
http://en.cppreference.com/w/cpp/regex/regex_token_iterator

  • “En este momento (usando std=c++14 en g++ (GCC) 4.9.2) todavía no acepta regex_match”. Eso no es cierto, probablemente lo estés usando mal.

    –Jonathan Wakely

    29/09/2017 a las 11:45

  • Su código no es “un enfoque que funcione como regex_match” porque esa función intenta hacer coincidir las subcadenas, no la cadena completa, por lo que sigo pensando que lo está usando mal. Puedes hacerlo con std::regex_search aunque, mira wandbox.org/permlink/rLbGyYcYGNsBWsaB

    –Jonathan Wakely

    29 de septiembre de 2017 a las 11:58


¿Ha sido útil esta solución?

Esta web utiliza cookies propias y de terceros para su correcto funcionamiento y para fines analíticos y para mostrarte publicidad relacionada con sus preferencias en base a un perfil elaborado a partir de tus hábitos de navegación. Al hacer clic en el botón Aceptar, acepta el uso de estas tecnologías y el procesamiento de tus datos para estos propósitos. Configurar y más información
Privacidad