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

นอกจากนี้ regex ยังทำงานได้ดีถ้าฉันมีเพียงสองรูปแบบทางเลือกเช่นst|mtดังนั้นดูเหมือนว่ารูปแบบสุดท้ายจะไม่ตรงกันด้วยเหตุผลบางประการ รหัสทำงานได้ดีกับคอมไพเลอร์ Apple LLVM

มีความคิดเห็นเกี่ยวกับวิธีแก้ปัญหาหรือไม่?

การปรับปรุง(st|mt)|trวิธีการแก้ปัญหาที่เป็นไปได้คือการใช้กลุ่มที่จะใช้ทางเลือกหลายเช่น


9
ใช่<regex>การสนับสนุนของ libstdc ++ ไม่สมบูรณ์ เราช่วยอะไรคุณได้บ้าง?
kennytm

10
สำหรับสถานะregexใน libstdc ++ โปรดดูที่gcc.gnu.org/onlinedocs/libstdc++/manual/…
ecatmur

51
แต่อย่างจริงจังใครที่จัดส่งการใช้งาน regex_search ที่ "ส่งคืนเท็จ" เท่านั้นเป็นความคิดที่ดี? "โอ้เราบันทึกไว้" ดูเหมือนจะตอบกลับอย่างอ่อนแรง
Paul Rubel

4
@ AK4749: นี่ไม่ใช่ข้อผิดพลาด มันไม่ได้ดำเนินการทันที แม้ว่าจำนวนครั้งที่คำถามนี้ปรากฏขึ้นจะน่าตกใจโดยเฉพาะอย่างยิ่งเนื่องจากไม่มีอะไรเปลี่ยนแปลงเกี่ยวกับ libstdc ++ <regex>ในช่วง 3-4 ปีที่ผ่านมา (เช่นเดียวกับ: ยังคงไม่ได้ใช้งาน)
rubenvb

5
@KeithThompson แม้ว่าจะเป็นเรื่องจริงที่<regex>จัดเตรียมโดย libstdc ++ (ไลบรารีมาตรฐาน GCC) ไม่ใช่gcc(ส่วนหน้าของคอมไพเลอร์) แต่เป็นส่วนหนึ่งของ GCC (โครงการ) ดู"libstdc ++ - v3 ได้รับการพัฒนาและปล่อยออกมาเป็นส่วนหนึ่งของ GCC" หาก distro ของคุณเลือกที่จะแยกมันออกเป็นแพ็คเกจแยกต่างหากที่ไม่เกี่ยวข้องกับ GCC
Jonathan Wakely

คำตอบ:


168

<regex> ถูกนำไปใช้และเผยแพร่ใน GCC 4.9.0

ใน (เก่า) รุ่นของ GCC ก็จะไม่ได้ดำเนินการ

<regex>โค้ดต้นแบบดังกล่าวถูกเพิ่มเมื่อการสนับสนุน C ++ 0x ของ GCC ทั้งหมดได้รับการทดลองอย่างมากติดตามแบบร่าง C ++ 0x ในช่วงต้นและพร้อมให้ผู้คนทดลองใช้ ที่ทำให้ผู้คนสามารถค้นหาปัญหาและให้ข้อเสนอแนะแก่คณะกรรมการมาตรฐานก่อนที่จะสรุปมาตรฐาน ในเวลานั้นผู้คนจำนวนมากรู้สึกขอบคุณที่สามารถเข้าถึงคุณสมบัติขอบเลือดออกมานานก่อนที่ C ++ 11 จะเสร็จสิ้นและก่อนที่คอมไพเลอร์อื่น ๆ จะให้การสนับสนุนใด ๆและข้อเสนอแนะนั้นช่วยปรับปรุง C ++ 11 ได้จริงๆ นี่คือสิ่งที่ดีTM TM

<regex>รหัสก็ไม่เคยอยู่ในสถานะที่มีประโยชน์ แต่ถูกบันทึกว่าเป็นความคืบหน้าในการทำงานเหมือนบิตอื่น ๆ ของรหัสในเวลานั้น มีการเช็คอินและเปิดให้ผู้อื่นทำงานร่วมกันได้หากต้องการโดยตั้งใจว่าจะเสร็จสิ้นในที่สุด

นั่นคือวิธีการทำงานของโอเพ่นซอร์สบ่อยครั้ง: ปล่อยก่อนกำหนดปล่อยบ่อย - น่าเสียดายในกรณีที่<regex>เรามีเพียงส่วนแรกที่ถูกต้องและไม่ใช่ส่วนที่มักจะทำให้การใช้งานเสร็จสิ้น

ส่วนใหญ่ของห้องสมุดมีความสมบูรณ์มากขึ้นและตอนนี้มีการใช้งานเกือบเต็มรูปแบบแล้ว แต่<regex>ยังไม่เสร็จสมบูรณ์ดังนั้นห้องสมุดจึงอยู่ในสถานะที่ยังไม่เสร็จเหมือนเดิมตั้งแต่มีการเพิ่มเข้ามา

แต่อย่างจริงจังใครที่จัดส่งการใช้งาน regex_search ที่ "ส่งคืนเท็จ" เท่านั้นเป็นความคิดที่ดี?

สองสามปีที่ผ่านมาไม่ใช่ความคิดที่เลวร้ายนักเมื่อ C ++ 0x ยังอยู่ระหว่างดำเนินการและเราได้จัดส่งการใช้งานบางส่วนจำนวนมาก ไม่มีใครคิดว่ามันจะยังคงใช้งานไม่ได้เป็นเวลานานดังนั้นด้วยการมองย้อนกลับอาจจะถูกปิดใช้งานและต้องใช้มาโครหรือตัวเลือกในตัวเพื่อเปิดใช้งาน แต่เรือลำนั้นแล่นไปนานแล้ว มีสัญลักษณ์ที่ส่งออกจากlibstdc ++ ดังนั้นไลบรารีที่ขึ้นอยู่กับโค้ด regex ดังนั้นเพียงแค่ลบออก (กล่าวคือ 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

มาโคร

  • _GLIBCXX_REGEX_DFS_QUANTIFIERS_LIMITจะถูกกำหนดไว้ในbits/regex.tccใน4.9.x
  • _GLIBCXX_REGEX_STATE_LIMITจะถูกกำหนดไว้ในbits/regex_automatron.hใน5+
  • _GLIBCXX_RELEASEถูกเพิ่มเข้ามา7+เป็นผลมาจากคำตอบนี้และเป็นรุ่นใหญ่ GCC

การทดสอบ

คุณสามารถทดสอบกับ 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ในส่วนหัวเพื่อไม่ให้ลืม - ขอบคุณ!
Jonathan Wakely

1
@JonathanWakely ได้เพิ่ม78,905 ฉันไม่แน่ใจว่าจะทำให้มันกลายเป็นจุดบกพร่องในการปรับปรุงได้อย่างไร แต่ตอนนี้มันอยู่ในระบบแล้ว
Matt Clarkson

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" ไม่เป็นความจริงคุณอาจใช้ผิด
Jonathan Wakely

1
รหัสของคุณไม่ใช่ "วิธีการทำงานเหมือน regex_match" เนื่องจากฟังก์ชันนั้นพยายามจับคู่สตริงย่อยไม่ใช่สตริงทั้งหมดดังนั้นฉันจึงยังคิดว่าคุณใช้ผิด คุณสามารถทำได้โดยstd::regex_searchดูที่wandbox.org/permlink/rLbGyYcYGNsBWsaB
Jonathan Wakely
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.