2009-04-07 34 views
5

Tôi tò mò, không ai biết cách tốt để thực hiện khớp cụm từ thông dụng trong C? Cách duy nhất tôi có thể nghĩ đến là thông qua Flex. Đây có phải là cách duy nhất hoặc có cách nào tốt hơn không?Cụm từ thông dụng trong C

Cảm ơn!

Trả lời

13

Uh ... Cách tốt nhất là để

#include <regex.h> 

Đó là POSIX standard API cho các biểu thức thông thường.

Đối với các hệ thống không phải POSIX, việc cuộn của riêng bạn là một giải pháp thay thế, động cơ regex cơ bản không quá khó thực hiện. Tôi chắc chắn rằng có những giải pháp off-the-shelf quá, tôi đã không neded một.

Nghĩ về nó, tôi nghĩ rằng glib có một.

+1

không viết động cơ regex của riêng bạn. đó là một lời khuyên khủng khiếp. –

0

lẽ this article sẽ giúp? Nó cho bạn thấy cách sử dụng các hàm regex được xác định trong regex.h.

Có, không phải là posix regex chỉ tuyệt vời họ có tất cả, vì vậy tôi tự hỏi tại sao họ không ở trong C? Vâng, Tôi tìm thấy câu trả lời và tôi đã hạnh phúc, họ đang có, và heres làm thế nào để sử dụng họ

11

Tùy thuộc vào những gì phương ngữ bạn đang tìm kiếm và những gì nền tảng bạn đang ở trên:

  • Biểu thức chính quy POSIX có thể nằm trong thư viện C chuẩn - xem <regex.h> và regcomp, regerror, regexec, regfree.
  • libPCRE cung cấp hầu hết regex mở rộng perl của tính năng
  • lém lỉnh có GRegex
  • Henry Spencer's Tcl Regex library.

Henry Spencer cũng đã thực hiện một regex library khác, được sử dụng bởi các phiên bản hiện tại của TCL và PostgreSQL. Điều này rất thú vị vì nó là một triển khai NFA/DFA lai.

Quy định chấp nhận cùng một chuỗi nhiều cách (như a * a?) Vốn đã yêu cầu NFA. Việc thực hiện thông thường mô hình NFA như là một DFA sử dụng backtracking, có thể được nhiều như O (2^chiều dài (đầu vào)) cho mô hình đặc biệt thoái hóa. Tuy nhiên, việc triển khai đệ quy đơn giản có thể được mở rộng bằng cách thu thập, quay lại, gọi lại mã và tất cả các tính năng "bổ sung" thông thường mà nhiều ngôn ngữ cung cấp ngoài thử nghiệm cho các kết quả phù hợp.

Cách tiếp cận "NFA" theo dõi nhiều trạng thái hiện tại và cập nhật tất cả các trạng thái đó với từng ký tự đến (Xem phần ghi của Ross Cox Thompson NFA regexes để được giải thích thêm). Cách tiếp cận này là O (input.length * pattern.length), nhanh hơn - vô cùng trong trường hợp xấu nhất - nhưng không thể thực hiện backrefs hoặc capture vì nó không theo dõi làm thế nào nó đã ở trạng thái.

Cách tiếp cận của Spencer là lai, biên dịch một số phần của mẫu thành phương pháp NFA và chỉ sử dụng backtracking khi cần thiết cho các ảnh chụp thực sự được yêu cầu. Đây thường là một chiến thắng đáng kể (xem số position in the regex-dna shootout của TCL).

+0

Giải thích regex cực kỳ phong cách NFA sử dụng backtracking, trong khi phong cách DFA thì không? – Vatine

+0

Regexes có thể chấp nhận cùng một chuỗi nhiều cách vốn cần NFA. Việc thực hiện thông thường như một DFA + backtracking là O (2^n). Cách tiếp cận "NFA" giữ nhiều trạng thái hiện tại và cập nhật tất cả chúng với mỗi ký tự đến (O (n * m). Xem http://swtch.com/~rsc/regexp/regexp1.html – puetzk

1

Một cách tiếp cận hoàn toàn khác nhau là cố gắng một Parsing Expression Grammar (PEG). PEG có vấn đề khớp mẫu từ quan điểm của một trình phân tích cú pháp và thậm chí có thể tận dụng nhiều quy tắc tạo thành một ngữ pháp hoàn chỉnh. Điều đó làm cho nó có thể viết biểu thức phù hợp với dấu ngoặc đơn cân bằng, mà nếu không khá khó để thể hiện trong hầu hết các phương ngữ regexp.

Mặc dù chốt là tương đối mới, cần có một vài hiện thực ra có được sử dụng từ C.

Việc thực hiện PEG Cá nhân tôi đã sử dụng là LPeg. Nó được ràng buộc gọn gàng với Lua, và tình cờ được viết bởi một trong những tác giả chính của Lua, Roberto Ierusalimschy. Nó cung cấp một thực hiện PEG hoàn chỉnh, và cũng bao gồm một bộ chuyển đổi dịch một regexp thành PEG tương đương để thực thi.

Liên kết lõi Lua với chương trình C chỉ để truy cập LPeg có vẻ quá mức cần thiết, nhưng thực sự không khó, ngay cả khi bạn không có kế hoạch sử dụng Lua cho các mục đích khác.

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