Gcc 4.8 trở xuống có lỗi về biểu thức chính quy không?


101

Tôi đang cố gắng sử dụng std :: regex trong đoạn mã C ++ 11, nhưng có vẻ như hỗ trợ có một chút lỗi. Một ví dụ:

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

kết quả đầu ra:

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

khi được biên dịch với gcc (MacPorts gcc47 4.7.1_2) 4.7.1, với

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

hoặc là

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

Bên cạnh đó, regex hoạt động tốt nếu tôi chỉ có hai mẫu thay thế, ví dụ st|mt, vì vậy có vẻ như mẫu cuối cùng không khớp vì một số lý do. Mã hoạt động tốt với trình biên dịch LLVM của Apple.

Bất kỳ ý tưởng về cách giải quyết vấn đề?

Cập nhật một giải pháp khả thi là sử dụng các nhóm để triển khai nhiều giải pháp thay thế, ví dụ (st|mt)|tr.


9
Có, <regex>hỗ trợ của libstdc ++ chưa hoàn thành. Chúng tôi có thể giúp gì cho bạn?
kennytm

10
Để biết trạng thái của regextrong libstdc ++, hãy xem gcc.gnu.org/onlineocs/libstdc++/manual/…
ecatmur 21/09/12

51
Nghiêm túc mà nói, ai mặc dù vận chuyển một triển khai regex_search chỉ có "return false" là một ý tưởng hay? "Ồ, chúng tôi đã ghi lại nó" có vẻ như một câu trả lời yếu ớt.
Paul Rubel

4
@ AK4749: đây không phải là lỗi. Nó chỉ hoàn toàn không hoàn thành. Mặc dù số lần câu hỏi này xuất hiện là đáng báo động, đặc biệt là vì không có gì thay đổi về libstdc ++ <regex>trong 3-4 năm qua (như trong: nó vẫn chưa hoàn thành).
rubenvb

5
@KeithThompson, mặc dù đúng là nó <regex>được cung cấp bởi libstdc ++ (thư viện chuẩn GCC) chứ không phải gcc(giao diện người dùng của trình biên dịch), nó là một phần của GCC (dự án). Xem "libstdc ++ - v3 được phát triển và phát hành như một phần của GCC" . Nếu bản phân phối của bạn chọn chia nó thành một gói riêng biệt thì không liên quan gì đến GCC.
Jonathan Wakely

Câu trả lời:


168

<regex> đã được triển khai và phát hành trong GCC 4.9.0.

Trong phiên bản GCC (cũ hơn) của bạn, nó không được triển khai .

<regex>Mã nguyên mẫu đó đã được thêm vào khi tất cả hỗ trợ C ++ 0x của GCC đều mang tính thử nghiệm cao , theo dõi các bản nháp C ++ 0x ban đầu và được cung cấp cho mọi người thử nghiệm. Điều đó cho phép mọi người tìm ra vấn đề và đưa ra phản hồi cho ủy ban tiêu chuẩn trước khi tiêu chuẩn được hoàn thiện. Vào thời điểm đó, rất nhiều người cảm thấy biết ơn vì đã có quyền truy cập vào các tính năng lợi hại từ rất lâu trước khi C ++ 11 hoàn thành và trước khi nhiều trình biên dịch khác cung cấp bất kỳ hỗ trợ nào và phản hồi đó thực sự giúp cải thiện C ++ 11. Đây là một điều tốt TM .

Các <regex>mã đã không bao giờ ở trong tình trạng rất hữu ích, nhưng được thêm vào như một tác phẩm dở dang như nhiêu bit khác của mã vào thời điểm đó. Nó đã được đăng ký và sẵn sàng cho những người khác cộng tác nếu họ muốn, với ý định cuối cùng nó sẽ hoàn thành.

Đó thường là cách mã nguồn mở hoạt động: Phát hành sớm, phát hành thường xuyên - thật không may trong trường hợp <regex>chúng tôi chỉ làm đúng phần ban đầu chứ không phải phần thường đã hoàn thành việc triển khai.

Hầu hết các phần của thư viện đã hoàn thiện hơn và hiện đã gần như được thực hiện đầy đủ, nhưng <regex>chưa hoàn thành, vì vậy nó vẫn ở trạng thái chưa hoàn thành như cũ kể từ khi được thêm vào.

Nghiêm túc mà nói, ai mặc dù vận chuyển triển khai regex_search mà chỉ có "return false" là một ý tưởng hay?

Đó không phải là một ý tưởng tồi cách đây vài năm, khi C ++ 0x vẫn đang trong quá trình hoàn thiện và chúng tôi đã gửi rất nhiều bản triển khai từng phần. Không ai nghĩ rằng nó sẽ không sử dụng được trong thời gian dài như vậy, với nhận thức muộn màng, có lẽ nó đã bị vô hiệu hóa và cần có tùy chọn macro hoặc thời gian tích hợp để kích hoạt nó. Nhưng con tàu đó đã ra khơi từ lâu. Có các ký hiệu được xuất từ libstdc ++. Nên thư viện phụ thuộc vào mã regex, vì vậy chỉ cần xóa nó (trong GCC 4.8) sẽ không phải là chuyện nhỏ.


12

Phát hiện tính năng

Đây là đoạn mã để phát hiện xem việc libstdc++triển khai có được triển khai với C tiền xử lý xác định:

#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

Macro

  • _GLIBCXX_REGEX_DFS_QUANTIFIERS_LIMITđược định nghĩa trong bits/regex.tcctrong4.9.x
  • _GLIBCXX_REGEX_STATE_LIMITđược định nghĩa trong bits/regex_automatron.htrong5+
  • _GLIBCXX_RELEASEđã được thêm vào 7+do câu trả lời này và là phiên bản chính của GCC

Thử nghiệm

Bạn có thể kiểm tra nó với GCC như sau:

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

Các kết quả

Dưới đây là một số kết quả cho các trình biên dịch khác nhau:


$ 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

Đây là những con rồng

Điều này hoàn toàn không được hỗ trợ và dựa vào việc phát hiện các macro riêng mà các nhà phát triển GCC đã đưa vào bits/regex*tiêu đề. Họ có thể thay đổi và biến mất bất cứ lúc nào . Hy vọng rằng chúng sẽ không bị xóa trong các bản phát hành 4.9.x, 5.x, 6.x hiện tại nhưng chúng có thể biến mất trong các bản phát hành 7.x.

Nếu các nhà phát triển GCC đã thêm một #define _GLIBCXX_HAVE_WORKING_REGEX 1(hoặc một cái gì đó, gợi ý gợi ý về cách di chuyển) trong bản phát hành 7.x vẫn tồn tại, thì đoạn mã này có thể được cập nhật để bao gồm đoạn mã đó và các bản phát hành GCC sau này sẽ hoạt động với đoạn mã trên.

Theo như tôi biết, tất cả các trình biên dịch khác đều hoạt động <regex>khi __cplusplus >= 201103Lngoại trừ YMMV.

Rõ ràng là điều này sẽ hoàn toàn bị phá vỡ nếu ai đó định nghĩa _GLIBCXX_REGEX_DFS_QUANTIFIERS_LIMIThoặc _GLIBCXX_REGEX_STATE_LIMITmacro bên ngoài stdc++-v3tiêu đề.


Rất đẹp! Tôi sẽ đề xuất kiểm tra macro bảo vệ tiêu đề từ một trong những tiêu đề mới trong GCC 4.9, nhưng chúng không có bảo vệ: - \ Các macro không thay đổi đối với GCC 7, nhưng về mặt lý thuyết thì chúng có thể làm được đối với GCC 8+, vì vậy vui lòng gửi yêu cầu nâng cao tại gcc.gnu.org/bugzilla để yêu cầu một cái gì đó giống như _GLIBCXX_REGEX_IS_OK_NOW_KTHXBAItrong tiêu đề, để nó không bị quên - cảm ơn!
Jonathan Wakely

1
@JonathanWakely đã thêm 78905 . Tôi không chắc làm thế nào để biến điều đó thành lỗi nâng cao nhưng hiện nó đã có trong hệ thống.
Matt Clarkson

1

Tại thời điểm này (sử dụng std = c ++ 14 trong g ++ (GCC) 4.9.2) vẫn không chấp nhận regex_match.

Đây là một cách tiếp cận hoạt động giống như regex_match nhưng sử dụng sregex_token_iterator để thay thế. Và nó hoạt động với 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;

nó sẽ in 1 2 3

bạn có thể đọc tham chiếu sregex_token_iterator trong: http://en.cppreference.com/w/cpp/regex/regex_token_iterator


1
"Tại thời điểm này (sử dụng std = c ++ 14 trong g ++ (GCC) 4.9.2) vẫn không chấp nhận regex_match." Điều đó không đúng, có lẽ bạn đang sử dụng sai.
Jonathan Wakely

1
Mã của bạn không phải là "một cách tiếp cận hoạt động như regex_match" vì hàm đó cố gắng khớp các chuỗi con, không phải toàn bộ chuỗi, vì vậy tôi vẫn nghĩ rằng bạn đang sử dụng nó sai. Bạn có thể làm điều đó với std::regex_searchdù, xem wandbox.org/permlink/rLbGyYcYGNsBWsaB
Jonathan Wakely
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.