नियमित अभिव्यक्ति के बारे में 4.8 या उससे पहले छोटी गाड़ी है?


101

मैं एक सी + + 11 कोड के कोड में std :: regex का उपयोग करने की कोशिश कर रहा हूं, लेकिन ऐसा प्रतीत होता है कि समर्थन थोड़ा छोटा है। एक उदाहरण:

#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
Libstdcregex ++ की स्थिति के लिए , gcc.gnu.org/onbuildocs/libstdc++/manual/…
ecatmur

51
गंभीरता से हालांकि, हालांकि, जो कि regex_search के कार्यान्वयन को शिपिंग करता है जो केवल "झूठे वापस करता है" एक अच्छा विचार था? "ओह, हमने इसे प्रलेखित किया" एक कमजोर उत्तर की तरह लगता है।
पॉल रूबेल

4
@ AK4749: यह कोई त्रुटि नहीं है। यह केवल एकतरफा लागू है। हालाँकि यह प्रश्न कितनी बार दिखाई देता है, यह चिंताजनक है, विशेष रूप से क्योंकि <regex>पिछले 3-4 वर्षों में libstdc ++ के बारे में कुछ भी नहीं बदला गया है (जैसा कि: यह अभी भी लागू नहीं हुआ है)।
rubenvb

5
@KeithThompson, जबकि यह सच है कि <regex>libstdc ++ (जीसीसी मानक पुस्तकालय) द्वारा प्रदान किया गया है gcc(संकलक सामने का छोर) नहीं, यह जीसीसी (परियोजना) का हिस्सा है। देखें "libstdc ++ - v3 विकसित और जीसीसी के हिस्से के रूप में जारी किया गया है" । यदि आपका डिस्ट्रो इसे एक अलग पैकेज में विभाजित करने का विकल्प चुनता है जिसका जीसीसी से कोई लेना-देना नहीं है।
जोनाथन वेकली

जवाबों:


168

<regex> लागू किया गया और जीसीसी 4.9.0 में जारी किया गया।

जीसीसी के आपके (पुराने) संस्करण में, इसे लागू नहीं किया गया है

उस प्रोटोटाइप <regex>कोड को तब जोड़ा गया था जब GCC के C ++ 0x सभी समर्थन अत्यधिक प्रायोगिक थे, प्रारंभिक C ++ 0x ड्राफ्ट पर नज़र रखने और लोगों को प्रयोग करने के लिए उपलब्ध कराया जा रहा था। इससे लोगों को समस्याएं खोजने और मानक को अंतिम रूप देने से पहले मानक समिति को प्रतिक्रिया देने की अनुमति मिली। उस समय बहुत से लोग आभारी थे कि सी ++ 11 समाप्त होने से पहले रक्तस्रावी बढ़त सुविधाओं तक पहुंच थी और इससे पहले कि कई अन्य संकलक किसी भी समर्थन प्रदान करते हैं, और उस प्रतिक्रिया ने वास्तव में सी ++ 11 को बेहतर बनाने में मदद की। यह एक अच्छी बात थी टीएम

<regex>कोड एक उपयोगी राज्य में कभी नहीं था, लेकिन एक काम में प्रगति समय कोड के कई अन्य बिट्स की तरह के रूप में जोड़ा गया है। इसमें जाँच की गई और दूसरों के लिए उपलब्ध कराने के लिए यदि वे चाहते हैं तो इस इरादे के साथ कि यह अंततः समाप्त हो जाएगा।

यह अक्सर ऐसा होता है कि ओपन सोर्स कैसे काम करता है: जल्दी रिलीज करें, अक्सर रिलीज करें - दुर्भाग्य से <regex>हम केवल शुरुआती हिस्से को सही पाते हैं और अक्सर उस हिस्से को नहीं जो कार्यान्वयन को समाप्त कर देता।

पुस्तकालय के अधिकांश भाग अधिक पूर्ण थे और अब लगभग पूरी तरह से लागू हो चुके हैं, लेकिन <regex>ऐसा नहीं किया गया है, इसलिए इसे जोड़ने के बाद से यह एक ही अधूरी स्थिति में रहा।

गंभीरता से, हालांकि, जो कि regex_search के कार्यान्वयन को शिपिंग करता है, जो केवल "झूठे वापस करता है" एक अच्छा विचार था?

यह कुछ साल पहले ऐसा बुरा विचार नहीं था, जब C ++ 0x अभी भी प्रगति पर था और हमने बहुत सारे आंशिक कार्यान्वयन किए। किसी ने भी नहीं सोचा था कि यह इतने लंबे समय तक अनुपयोगी रहेगा, यदि कोई बाधा है, तो शायद इसे अक्षम कर दिया जाना चाहिए और इसे सक्षम करने के लिए मैक्रो या बिल्ट-टाइम विकल्प की आवश्यकता होगी। लेकिन वह जहाज बहुत पहले ही रवाना हो गया था। Libstdc ++ से निर्यात किए गए प्रतीक हैं । इसलिए लाइब्रेरी जो कि रेगेक्स कोड पर निर्भर करती है, इसलिए बस इसे हटा देना (इन, कहते हैं, जीसीसी 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

मैक्रो

  • _GLIBCXX_REGEX_DFS_QUANTIFIERS_LIMITमें परिभाषित किया bits/regex.tccगया है4.9.x
  • _GLIBCXX_REGEX_STATE_LIMITमें परिभाषित किया bits/regex_automatron.hगया है5+
  • _GLIBCXX_RELEASEइस उत्तर के7+ परिणामस्वरूप जोड़ा गया था और 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

खतरनाक इलाके

यह पूरी तरह से असमर्थ है और जीसीसी डेवलपर्स ने bits/regex*हेडर में डाल दिया है कि निजी मैक्रो का पता लगाने पर निर्भर करता है । वे बदल सकते थे और कभी भी चले जा सकते थे । उम्मीद है, उन्हें वर्तमान 4.9.x, 5.x, 6.x रिलीज़ में नहीं हटाया जाएगा, लेकिन वे 7.x रिलीज़ में दूर जा सकते हैं।

यदि GCC डेवलपर्स ने #define _GLIBCXX_HAVE_WORKING_REGEX 17.x रिलीज़ में एक (या कुछ और, हिंट हिड नजेज) जोड़ा है, जो बरकरार है, तो इस स्निपेट को शामिल करने के लिए अपडेट किया जा सकता है और बाद में जीसीसी रिलीज़ स्निपेट के साथ काम करेगा।

जहाँ तक मुझे पता है, अन्य सभी संकलक एक काम <regex>करते हैं, __cplusplus >= 201103Lलेकिन YMMV।

जाहिर है कि यह पूरी तरह से टूट जाएगा अगर किसी ने हेडर के बाहर _GLIBCXX_REGEX_DFS_QUANTIFIERS_LIMITया _GLIBCXX_REGEX_STATE_LIMITमैक्रोज़ को परिभाषित किया stdc++-v3


बहुत अच्छा! मैं हेडर गार्ड मैक्रो के लिए जीसीसी 4.9 में नया है, जो हेडर गार्ड मैक्रो के लिए जाँच करने का सुझाव देने जा रहा था, लेकिन उनके पास गार्ड नहीं हैं: - जीसीसी 7 के लिए मैक्रोज़ नहीं बदल रहे हैं, लेकिन सैद्धांतिक रूप से वे जीसीसी के लिए कर सकते हैं 8+, इसलिए कृपया gcc.gnu.org/bugzilla पर _GLIBCXX_REGEX_IS_OK_NOW_KTHXBAIहेडर में कुछ मांगने के लिए एन्हांसमेंट अनुरोध दर्ज करें , ताकि यह भूल न जाए - धन्यवाद!
जोनाथन वैक्ली

1
@JonathanWakely ने 78905 जोड़े हैं । मुझे यकीन नहीं है कि कैसे एक वृद्धि बग में बनाने के लिए, लेकिन यह अब सिस्टम में है।
मैट क्लार्कसन

1

इस समय (st ++ = c ++ 14 in 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
"इस समय (st ++ = c ++ 14 में g ++ (GCC) 4.9.2 का उपयोग करके) अभी भी regex_match को स्वीकार नहीं कर रहा है।" यह सच नहीं है, आप शायद इसे गलत उपयोग कर रहे हैं।
जोनाथन वेकली

1
आपका कोड "एक दृष्टिकोण जो regex_match की तरह काम करता है" नहीं है, क्योंकि यह फ़ंक्शन उप-स्ट्रिंग्स से मेल खाने की कोशिश करता है, न कि पूरे स्ट्रिंग, इसलिए मुझे अभी भी लगता है कि आप इसे गलत उपयोग कर रहे हैं। आप इसके साथ कर सकते हैं std::regex_search, फिर भी देखें wandbox.org/permlink/rLbGyYcYGNsBWsaB
जोनाथन
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.