2011-01-21 35 views
5

Tôi có tài liệu LaTeX tôi muốn khớp. Và tôi cần một trận đấu RegEx phù hợp với những điều sau:Làm cách nào để khớp các dấu ngoặc ôm bằng cách sử dụng cụm từ thông dụng trong PHP?

\ # the backslash in the beginning 
[a-zA-Z]+ #a word 
(\{.+\})* # any amount of {something} 

Tuy nhiên, cô ấy là người nắm bắt;

Trong dòng cuối cùng, nó 1. cần phải tham lam và 2. cần phải có số phù hợp là {} bên trong chính nó.

Có nghĩa là nếu tôi có chuỗi \test{something\somthing{9}} , nó sẽ khớp với toàn bộ. Và nó cần phải theo thứ tự đó ({}). Vì vậy, nó không phù hợp với những điều sau đây: một hệ thống chuẩn bị tài liệu

\ LaTeX {} được cho \ TeX {}

chỉ

\ LaTeX {}

\ TeX {}

Giúp đỡ bất kỳ ai? Có lẽ ai đó có ý tưởng phù hợp hơn? Tôi có nên sử dụng cụm từ thông dụng không?

+2

Nó không phải là một điều bình thường bạn muốn kết hợp, biểu hiện rất thường xuyên không sự lựa chọn tốt nhất. Điều đó đang được nói, bạn có thể * * làm điều đó, vì hầu hết các động cơ biểu hiện thường xuyên không phải là bình thường những ngày này, nhưng nó vẫn không phải là một ý tưởng tốt. –

+0

Nếu tôi có sự lựa chọn nào khác mà tôi đã có thể đi cho nó. Nhưng tôi không biết về bất kỳ thứ gì khác mà tôi có thể sử dụng. Bạn có ý tưởng nào không? Nếu không, có vẻ như tôi đang bị mắc kẹt chiều rộng RegEx. – Knarf

+0

Nó không chỉ là một số chẵn của '{' và '}' (mà bạn có thể làm với regex), nhưng bạn cũng muốn chắc chắn rằng '}} {{' bị từ chối (có số lượng bằng '{' và '} '!), và bạn muốn loại bỏ' {' và '}' khi chúng xảy ra trong bình luận-dòng. Tóm lại: regex không phù hợp với điều này. –

Trả lời

2

Điều này có thể được thực hiện với đệ quy:

$input = "\LaTeX{} is a document preparation system for the \TeX{} 
\latex{something\somthing{9}}"; 

preg_match_all('~(?<token> 
     \\\\ # the slash in the beginning 
     [a-zA-Z]+ #a word 
     (\{[^{}]*((?P>token)[^{}]*)?\}) # {something} 
)~x', $input, $matches); 

này phù hợp một cách chính xác \LaTeX{}, \TeX{}, và \latex{something\somthing{9}}

-1

Thật không may, tôi tin rằng điều này là không thể. Kết hợp khung (phát hiện đúng cặp, dấu ngoặc lồng nhau) thường được sử dụng làm ví dụ về một vấn đề không thể giải quyết được với một máy trạng thái hữu hạn, chẳng hạn như trình phân tích biểu thức chính quy. Bạn có thể làm điều đó với ngữ cảnh tự do ngữ cảnh, nhưng đó không phải là cách làm việc của regex. Giải pháp tốt nhất của bạn là sử dụng regex như {*[^{}]*}* để kiểm tra ban đầu và sau đó là một tập lệnh ngắn khác để kiểm tra xem đó có phải là số chẵn hay không.

Kết luận: không thử và làm điều đó chỉ với regex. Đây không phải là một vấn đề có thể được giải quyết với regex một mình.

2

PHP thể được sử dụng vì nó hỗ trợ đệ quy regex khớp. Nhưng, như tôi đã nói, nếu bạn có nhận xét trong các chuỗi giống như LaTeX có thể có { hoặc } trong đó, điều này sẽ không thành công.

Một bản demo:

$text = 'This is a \LaTeX{ foo { bar { ... } baz test {} done } } document 
preparation system for the \TeX{a{b{c}d}e{f}g{h}i}-y people out there'; 
preg_match_all('/\\\\[A-Za-z]+(\{(?:[^{}]|(?1))*})/', $text, $matches, PREG_SET_ORDER); 
print_r($matches); 

trong đó sản xuất:

Array 
(
    [0] => Array 
     (
      [0] => \LaTeX{ foo { bar { ... } baz test {} done } } 
      [1] => { foo { bar { ... } baz test {} done } } 
     ) 

    [1] => Array 
     (
      [0] => \TeX{a{b{c}d}e{f}g{h}i} 
      [1] => {a{b{c}d}e{f}g{h}i} 
     ) 

) 

Một lời giải thích nhanh chóng:

\\\\   # the literal '\' 
[A-Za-z]+ # one or more letters 
(   # start capture group 1 <-----------------+ 
    \{   # the literal '{'       | 
    (?:  # start non-capture group A    | 
    [^{}] #  any character other than '{' and '}' | 
    |  #  OR         | 
    (?1)  #  recursively match capture group 1 ---+ 
)   # end non-capture group A 
    *   # non-capture group A zero or more times 
    }   # the literal '}' 
)   # end capture group 1 
Các vấn đề liên quan