2012-01-04 26 views
7

Xin chào, tôi đang sử dụng Thư viện chuẩn Regex (regcomp, regexec ..). Nhưng bây giờ theo yêu cầu tôi nên thêm hỗ trợ unicode vào mã của tôi cho các biểu thức thông thường.POSIX regex có cung cấp các ký tự unicode hoặc về cơ bản không phải là ascii không?

Thư viện chuẩn Regex có cung cấp ký tự unicode hoặc về cơ bản không phải ascii không? Tôi đã nghiên cứu trên Web và không nghĩ vậy.

Dự án của tôi là nhà phê bình tài nguyên vì vậy tôi không muốn sử dụng các thư viện lớn cho nó (ICU và Boost.Regex).

Bất kỳ trợ giúp nào sẽ được đánh giá cao ..

+1

Không phải là tôi biết, nhưng thư viện kế hoạch 9 regex là; một cổng unix là tại http://swtch.com/plan9port/unix/ dưới 'libregexp9' – Dave

Trả lời

6

Dường như POSIX Regex hoạt động đúng với ngôn ngữ UTF-8. Tôi vừa viết một bài kiểm tra đơn giản (xem bên dưới) và sử dụng nó để kết hợp chuỗi ký tự với một ký tự không gian chống lại regex "[[:alpha:]]" (ví dụ). Và mọi thứ hoạt động tốt.

Lưu ý: Điều chính bạn phải nhớ - chức năng regex có liên quan đến miền địa phương. Vì vậy, bạn phải gọi setlocale() trước đó.

#include <sys/types.h> 
#include <string.h> 
#include <regex.h> 
#include <stdio.h> 
#include <locale.h> 

int main(int argc, char** argv) { 
    int ret; 
    regex_t reg; 
    regmatch_t matches[10]; 

    if (argc != 3) { 
    fprintf(stderr, "Usage: %s regex string\n", argv[0]); 
    return 1; 
    } 

    setlocale(LC_ALL, ""); /* Use system locale instead of default "C" */ 

    if ((ret = regcomp(&reg, argv[1], 0)) != 0) { 
    char buf[256]; 
    regerror(ret, &reg, buf, sizeof(buf)); 
    fprintf(stderr, "regcomp() error (%d): %s\n", ret, buf); 
    return 1; 
    } 

    if ((ret = regexec(&reg, argv[2], 10, matches, 0)) == 0) { 
    int i; 
    char buf[256]; 
    int size; 
    for (i = 0; i < sizeof(matches)/sizeof(regmatch_t); i++) { 
     if (matches[i].rm_so == -1) break; 
     size = matches[i].rm_eo - matches[i].rm_so; 
     if (size >= sizeof(buf)) { 
     fprintf(stderr, "match (%d-%d) is too long (%d)\n", 
       matches[i].rm_so, matches[i].rm_eo, size); 
     continue; 
     } 
     buf[size] = '\0'; 
     printf("%d: %d-%d: '%s'\n", i, matches[i].rm_so, matches[i].rm_eo, 
      strncpy(buf, argv[2] + matches[i].rm_so, size)); 

    } 
    } 

    return 0; 
} 

Cách sử dụng Ví dụ:

$ locale 
LANG=ru_RU.UTF-8 
LC_CTYPE="ru_RU.UTF-8" 
LC_COLLATE="ru_RU.UTF-8" 
... (skip) 
LC_ALL= 
$ ./reg '[[:alpha:]]' ' 359 фыва' 
0: 5-7: 'ф' 
$ 

Chiều dài của kết quả phù hợp là hai byte vì chữ Cyrillic trong UTF-8 mất rất nhiều.

+0

tôi nghĩ rằng bạn hiểu lầm tôi. tôi muốn làm điều đó: ./reg 'ç' 'çilek45' – iyasar

+0

Vậy vấn đề là gì? Mã trên được in: '0: 0-2: 'ç'' với các tham số của bạn. Nghĩa là, nó hoạt động. –

+0

xin lỗi lỗi của tôi nó hoạt động nhờ .. – iyasar

6

Về cơ bản, POSIX regex không phải là nhận thức Unicode. Bạn có thể thử sử dụng chúng trên các ký tự Unicode, nhưng có thể có vấn đề với glyphs có nhiều mã hóa và các vấn đề khác mà các thư viện nhận biết Unicode xử lý cho bạn.

Từ tiêu chuẩn, IEEE Std 1003.1-2008:

Matching phải dựa trên các mẫu bit được sử dụng để mã hóa các nhân vật, không phải trên đại diện đồ họa của nhân vật. Điều này có nghĩa là nếu một bộ ký tự chứa hai hoặc nhiều mã hóa cho một biểu tượng đồ họa, hoặc nếu các chuỗi được tìm kiếm chứa văn bản được mã hóa trong nhiều hơn một mã, không cần thực hiện tìm kiếm bất kỳ biểu diễn nào khác của biểu tượng được mã hóa. Nếu điều đó là bắt buộc, người dùng có thể chỉ định các lớp tương đương có chứa tất cả các biến thể của biểu tượng đồ họa mong muốn.

Có thể libpcre sẽ phù hợp với bạn? Đó là hơi nặng hơn so với POSIX regexes, nhưng tôi sẽ nghĩ rằng nó nhẹ hơn ICU hoặc Boost.

0

Nếu bạn thực sự có nghĩa là "Chuẩn", nghĩa là std::regex từ C++ 11, thì tất cả những gì bạn cần làm là chuyển sang std::wregex (và std::wstring tất nhiên).

+0

Chúng đang nói về giao diện hệ thống regex.h như được chỉ định bởi tiêu chuẩn POSIX – Spookbuster

Các vấn đề liên quan