Gcc 4.8 veya önceki sürümler normal ifadelerle ilgili bir hata mı?


101

Std :: regex'i bir C ++ 11 kod parçasında kullanmaya çalışıyorum, ancak destek biraz hatalı görünüyor. Bir örnek:

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

çıktılar:

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 ile derlendiğinde, ya da

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

veya

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

Ayrıca, normal ifade sadece iki alternatif kalıbım varsa iyi çalışıyor, örneğin st|mt, sonuncusu bazı nedenlerden dolayı eşleşmiyor gibi görünüyor. Kod, Apple LLVM derleyicisiyle iyi çalışır.

Sorunun nasıl çözüleceğine dair bir fikriniz var mı?

Olası bir çözümü güncellemek , çoklu alternatifleri uygulamak için grupları kullanmaktır, örn (st|mt)|tr.


9
Evet libstdc ++ 'ın <regex>desteği eksik. Size ne yardımcı olabiliriz
kennytm

10
Libstdcregex ++ 'daki durumu için bkz. Gcc.gnu.org/onlinedocs/libstdc++/manual/…
ecatmur

52
Cidden, kim sadece "yanlış döndüren" bir regex_search uygulaması göndermenin iyi bir fikir olduğunu düşündü? "Oh, biz bunu belgeledik" zayıf bir cevap gibi görünüyor.
Paul Rubel

4
@ AK4749: Bu bir hata değil. Sadece tamamen uygulanmamış. Bu sorunun ortaya çıkma miktarı endişe verici olsa da, özellikle <regex>son 3-4 yılda libstdc ++ ile ilgili hiçbir şey değişmediğinden (olduğu gibi: uygulanmamış olarak kalır).
rubenvb

5
@KeithThompson, <regex>libstdc ++ (GCC standart kitaplığı) tarafından değil gcc(derleyici ön ucu) tarafından sağlandığı doğru olsa da, GCC'nin (proje) bir parçasıdır. Bkz. "Libstdc ++ - v3, GCC'nin bir parçası olarak geliştirildi ve yayınlandı" . Dağıtımınız onu ayrı bir pakete bölmeyi seçerse, bu GCC ile hiçbir ilgisi yoktur.
Jonathan Wakely

Yanıtlar:


170

<regex> GCC 4.9.0'da uygulanmış ve yayınlanmıştır.

GCC'nin (eski) sürümünüzde bu uygulanmaz .

Bu prototip <regex>kodu, GCC'nin tüm C ++ 0x desteği son derece deneysel olduğunda, erken C ++ 0x taslaklarını izlediğinde ve insanların denemeleri için kullanıma sunulduğunda eklendi. Bu, insanların problemleri bulmasına ve standart sonuçlandırılmadan önce standart komiteye geri bildirim vermesine izin verdi. O zamanlar pek çok insan, C ++ 11 bitmeden ve diğer birçok derleyici herhangi bir destek sağlamadan çok önce, son teknoloji özelliklere erişim sağladıkları için minnettardı ve bu geri bildirim, C ++ 11'in geliştirilmesine gerçekten yardımcı oldu. Bu bir Good Thing TM idi .

<regex>Kod yararlı bir halde değildi, ama bir eser-içinde-ilerleme anda kodun diğer birçok bit gibi eklenmiştir. Kontrol edildi ve sonunda bitmesi niyetiyle başkalarının isterlerse işbirliği yapmaları için sağlandı.

Açık kaynak çoğu zaman böyle çalışır: Erken yayınlayın, sık sık yayınlayın - ne yazık ki, <regex>yalnızca ilk kısmı doğru aldık ve uygulamayı tamamlayacak olan kısmı değil.

Kütüphanenin çoğu bölümü daha eksiksizdi ve şimdi neredeyse tamamen uygulanıyordu, ancak uygulanmamıştı, <regex>bu nedenle eklendiğinden beri aynı bitmemiş durumda kaldı.

Cidden, kim sadece "yanlış döndüren" bir regex_search uygulaması göndermenin iyi bir fikir olduğunu düşündü?

Birkaç yıl önce, C ++ 0x hala devam eden bir işken ve birçok kısmi uygulama gönderirken o kadar da kötü bir fikir değildi. Hiç kimse bu kadar uzun süre kullanılamayacağını düşünmedi, bu yüzden geriye dönüp bakıldığında, belki de devre dışı bırakılması ve etkinleştirmek için bir makro veya yerleşik zaman seçeneğine ihtiyaç duyması gerekirdi. Ama o gemi uzun zaman önce yelken açtı. Libstdc ++ ' dan dışa aktarılan semboller vardır , bu nedenle düzenli ifade koduna bağlı olan kitaplık, bu nedenle basitçe kaldırmak (örneğin, GCC 4.8 içinde) önemsiz olmazdı.


13

Özellik Algılama

Bu, libstdc++uygulamanın C ön işlemcisi tanımlarıyla uygulanıp uygulanmadığını algılayan bir kod parçacığıdır :

#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

Makrolar

  • _GLIBCXX_REGEX_DFS_QUANTIFIERS_LIMITolduğu belirlenen içinde bits/regex.tccde4.9.x
  • _GLIBCXX_REGEX_STATE_LIMITolduğu belirlenen içinde bits/regex_automatron.hde5+
  • _GLIBCXX_RELEASEbu cevabın7+ bir sonucu olarak eklendi ve GCC ana sürümüdür

Test yapmak

GCC ile şu şekilde test edebilirsiniz:

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

Sonuçlar

Çeşitli derleyiciler için bazı sonuçlar şunlardır:


$ 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

Burada ejderhalar olsun

Bu tamamen desteklenmez ve GCC geliştiricilerinin bits/regex*başlıklara koyduğu özel makroların tespitine dayanır . Her an değişip gidebilirler . Umarım mevcut 4.9.x, 5.x, 6.x sürümlerinde kaldırılmazlar, ancak 7.x sürümlerinde ortadan kalkabilirler.

GCC geliştiricileri #define _GLIBCXX_HAVE_WORKING_REGEX 17.x sürümüne kalıcı olan bir (veya bir şey, ipucu dürtükleme) eklediyse , bu kod parçası bunu içerecek şekilde güncellenebilir ve daha sonraki GCC sürümleri yukarıdaki kod parçacığı ile çalışacaktır.

Gibi bildiğim kadarıyla, diğer tüm derleyiciler bir çalışma var ymmv.<regex>__cplusplus >= 201103L

Açıkçası, birisi _GLIBCXX_REGEX_DFS_QUANTIFIERS_LIMITveya _GLIBCXX_REGEX_STATE_LIMITmakroları stdc++-v3başlıkların dışında tanımladıysa bu tamamen bozulacaktır .


Çok hoş! GCC 4.9'da yeni olan başlıklardan birinden başlık koruma makrosunun kontrol edilmesini önerecektim, ancak korumaları yok: - \ Makrolar GCC 7 için değişmiyor, ancak teorik olarak GCC için yapabilirler 8+, bu yüzden lütfen gcc.gnu.org/bugzilla adresinde _GLIBCXX_REGEX_IS_OK_NOW_KTHXBAIbaşlıklarda olduğu gibi bir şey isteyerek bir geliştirme isteği gönderin , böylece unutulmasın - teşekkürler!
Jonathan Wakely

1
@JonathanWakely 78905 ekledi . Bunu bir geliştirme hatası haline nasıl getireceğimi bilmiyorum ama artık sistemde.
Matt Clarkson

1

Şu anda (g ++ (GCC) 4.9.2'de std = c ++ 14 kullanarak) hala regex_match'i kabul etmiyor.

Burada regex_match gibi çalışan ancak bunun yerine sregex_token_iterator kullanan bir yaklaşım var. Ve g ++ ile çalışır.

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 yazdıracak

sregex_token_iterator referansını şu adreste okuyabilirsiniz: http://en.cppreference.com/w/cpp/regex/regex_token_iterator


1
"Şu anda (g ++ (GCC) 4.9.2'de std = c ++ 14 kullanarak) hala regex_match'i kabul etmiyor." Bu doğru değil, muhtemelen yanlış kullanıyorsunuzdur.
Jonathan Wakely

1
Kodunuz "regex_match gibi çalışan bir yaklaşım" değildir çünkü bu işlev tüm dizeyi değil alt dizeleri eşleştirmeye çalışır, bu yüzden hala yanlış kullandığınızı düşünüyorum. Bununla birlikte yapabilirsiniz std::regex_search, bkz. Wandbox.org/permlink/rLbGyYcYGNsBWsaB
Jonathan Wakely
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.