Чи є gcc 4.8 або попередні помилки щодо регулярних виразів?


101

Я намагаюся використовувати std :: regex у коді C ++ 11, але виявляється, що підтримка трохи помиляється. Приклад:

#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.


9
Так, підтримка libstdc ++ <regex>є неповною. Чим ми можемо вам допомогти?
kennytm

10
Про статус regexв libstdc ++ див. На сайті gcc.gnu.org/onlinedocs/libstdc++/manual/…
ecatmur

51
Якщо серйозно, то, хто хоч, що відправка на реалізацію regex_search, яка лише "повертає помилку", була гарною ідеєю? "О, ми це задокументували" видається слабкою відповіддю.
Пол Рубель

4
@ AK4749: це не помилка. Це просто безрезультатно. Хоча кількість запитань цього питання викликає занепокоєння, тим більше, що нічого не змінилося щодо libstdc ++ <regex>за останні 3-4 роки (як у: воно залишається без змін).
rubenvb

5
@KeithThompson, хоча це правда, що <regex>надається libstdc ++ (стандартна бібліотека GCC) не gcc(передній кінець компілятора), вона є частиною GCC (проект). Дивіться "libstdc ++ - v3 розробляється та випускається як частина GCC" . Якщо ваш дистрибутив вирішив розділити його на окремий пакет, це не має нічого спільного з GCC.
Джонатан Уейклі

Відповіді:


168

<regex> було реалізовано та випущено в GCC 4.9.0.

У вашій (старшій) версії GCC вона не реалізована .

Цей <regex>код прототипу був доданий, коли вся підтримка C ++ 0x GCC була високо експериментальною, відстежуючи ранні C ++ 0x чернетки та був доступний для експериментів з людьми. Це дозволило людям знайти проблеми та надати відгуки до стандартного комітету до його завершення. У той час багато людей були вдячні, що отримали доступ до особливостей кровотоку задовго до того, як C ++ 11 було закінчено, і до того, як багато інших компіляторів не надали будь-якої підтримки, і цей відгук справді допоміг покращити C ++ 11. Це була гарна річ ТМ .

<regex>Код ніколи не був в змозі корисного, але був доданий в якості роботи в прогрес , як і багато інших біти коду в той час. Він був зареєстрований і був доступний для співпраці інших, якщо вони захочуть, з наміром, що це буде закінчено в підсумку.

Ось так часто працює з відкритим кодом: випускайте достроково, часто випускайте випускайте - на жаль, у випадку, якщо <regex>ми отримали право лише на початку, а не на частину, яка закінчила б реалізацію.

Більшість частин бібліотеки були більш повними і зараз майже повністю реалізовані, але <regex> ще не були, тому вона залишалася в тому ж незавершеному стані з моменту її додавання.

Якщо серйозно, то, хто хоч, що відправка на реалізацію regex_search, яка лише "повертає помилку", була гарною ідеєю?

Це була не така погана ідея кілька років тому, коли C ++ 0x ще працював, і ми постачали багато часткових реалізацій. Ніхто не думав, що він буде залишатися непридатним так довго, тому, з огляду, може бути, його було вимкнено, і для його ввімкнення потрібен макрос або вбудований параметр. Але той корабель плив давно. Є експортовані символи з libstdc ++, тому бібліотека, яка залежить від коду регулярного виразу, так що просто видалити його (у скажімо, 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

Макроси

Тестування

Ви можете протестувати його за допомогою 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 працюватимуть із фрагментом вище.

Наскільки я знаю, всі інші компілятори мають роботу , <regex>коли , __cplusplus >= 201103Lале YMMV.

Очевидно, це повністю порушиться, якби хтось визначив _GLIBCXX_REGEX_DFS_QUANTIFIERS_LIMITабо _GLIBCXX_REGEX_STATE_LIMITмакроси поза stdc++-v3заголовками.


Дуже хороша! Я збирався запропонувати перевірити макрос захисту заголовка з одного із заголовків, який є новим у GCC 4.9, але вони не мають охоронців: - \ Макроси не змінюються для GCC 7, але теоретично вони могли би зробити для GCC 8+, тому, будь ласка, подайте запит на вдосконалення на адресу gcc.gnu.org/bugzilla із проханням щось схоже _GLIBCXX_REGEX_IS_OK_NOW_KTHXBAIна заголовки, щоб воно не забулося - дякую!
Джонатан Вейклі

1
@JonathanWakely додали 78905 . Я не впевнений, як зробити це в помилку покращення, але це зараз у системі.
Метт Кларксон

1

На даний момент (використовуючи std = c ++ 14 в g ++ (GCC) 4.9.2) все ще не приймається 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
"На даний момент (використовуючи std = c ++ 14 в g ++ (GCC) 4.9.2) все ще не приймається regex_match." Це неправда, ви, мабуть, неправильно використовуєте.
Джонатан Вейклі

1
Ваш код не є "підходом, який працює як regex_match", оскільки ця функція намагається відповідати підрядкам, а не всій рядку, тому я все ще думаю, що ви неправильно використовуєте його. Ви можете це зробити, std::regex_searchхоча дивіться wandbox.org/permlink/rLbGyYcYGNsBWsaB
Джонатан
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.