2011-06-17 19 views
9

Tại sao cả hai regex này lại khớp thành công?

if(preg_match_all('/$^/m',"",$array)) 
    echo "Match"; 

if(preg_match_all('/$^\n$/m',"\n",$array)) 
    echo "Match"; 

Trả lời

11

$^ là các ký tự meta có độ rộng bằng 0. Không giống như các ký tự meta khác như . khớp với một ký tự tại một thời điểm (trừ khi được sử dụng với số lượng), chúng không thực sự khớp với các ký tự chữ. Đây là lý do tại sao ^$ khớp với một chuỗi trống "", mặc dù regex (ký tự phân cách) chứa hai ký tự trong khi chuỗi rỗng chứa số không.

Việc chuỗi trống không chứa ký tự không quan trọng. Nó vẫn có một điểm bắt đầu và một điểm kết thúc, và vì nó là một chuỗi rỗng cả hai đều ở cùng một vị trí. Do đó, bất kể thứ tự hoặc số ^$ bạn sử dụng, tất cả các hoán vị của chúng phải khớp với chuỗi trống.


Trường hợp thứ hai của bạn hơi phức tạp hơn nhưng cũng áp dụng nguyên tắc tương tự.

Bộ sửa đổi m (PCRE_MULTILINE) chỉ yêu cầu công cụ PCRE cấp toàn bộ chuỗi tại một lần, bất kể dòng mới, nhưng chuỗi vẫn bao gồm "nhiều dòng". Sau đó, nó nhìn vào số ^$ dưới dạng "đầu dòng" và "cuối dòng" tương ứng.

Chuỗi "\n" về cơ bản được chia thành ba phần: "", "\n""" (vì dòng mới được bao quanh bởi khoảng trống ... nghe có vẻ thơ mộng).

Sau đó, những trận đấu theo:

  1. Các chuỗi rỗng đầu tiên được kết hợp bởi các bắt đầu $^ (như tôi giải thích ở trên).

  2. \n khớp với cùng một số \n trong regex của bạn.

  3. Chuỗi trống thứ hai được khớp với $ cuối cùng.

Và đó là cách trường hợp thứ hai của bạn dẫn đến kết quả trùng khớp.

+0

yes thats điểm! thanks – nEAnnam

+3

Là một thú vị sang một bên, tôi thấy kịch bản này tương tự như câu hỏi tại sao chuỗi rỗng là một chuỗi con của chính nó. Vì vậy, đây không phải là một câu hỏi ngu ngốc cả. Trong thực tế, tôi đã chỉ upvoted nó! – BoltClock

+0

+1 Câu trả lời hay. – BrunoLM

3

Không có. Trên thực tế, biểu thức $^ sẽ không bao giờ khớp nhau, bởi vì $ tượng trưng cho phần cuối của chuỗi trong khi ^ đại diện cho phần đầu. Nhưng như chúng ta biết, kết thúc không thể đến trước khi bắt đầu một chuỗi :)

^$ phải khớp với một chuỗi trống và chỉ có chuỗi đó.

Siêu ký hiệu "bắt đầu dòng" (^) chỉ khớp ở đầu chuỗi, trong khi ký hiệu siêu ký tự "cuối dòng" ($) chỉ khớp ở cuối chuỗi, [...]

Từ PCRE manpages

Lưu ý rằng, bằng cách thêm modifier PCRE_MULTILINE, $ trở EOL và ^ trở thành BOL, nó sẽ phù hợp (nhờ netcoder đã chỉ mà ra). Tuy nhiên, cá nhân tôi sẽ không sử dụng nó.

+0

vậy tại sao '/ $^\ n $/m', '\ n' khớp với – nEAnnam

+0

Có lẽ vì đó là lỗi trong công cụ regex yêu thích của bạn :) Hoặc có thể nó được xác định như vậy. Nhưng nó không có ý nghĩa hợp lý và bạn không bao giờ nên sử dụng nó. – fresskoma

+0

@nEAnnam: Điều đó không phù hợp với tôi và không nên. – BoltClock

0

Trong regex, ^ khớp với phần bắt đầu của chuỗi và $ khớp với phần cuối của chuỗi.

Do đó, regex /^$/ sẽ đối sánh thành công chuỗi hoàn toàn trống (và không có gì khác).

/$^/ sẽ không khớp với bất kỳ thứ gì, vì bạn không thể kết thúc chuỗi trước khi bắt đầu.

1

Regex.IsMatch ("", "$^") đối sánh trong C#, cũng vậy. Vì nó là một chuỗi rỗng, không có kích thước. Tại chỉ số -1, nó đồng thời ở cuối và đầu chuỗi, đồng thời. Câu hỏi hay!

+1

Có một kích thước ... nó là 0. (Xin lỗi, tôi không thể cưỡng lại;) – BoltClock

+0

@BoltClock. :-) Tôi nên nói, 'không có muỗng'. Ví dụ này uốn cong tâm trí của tôi như The Matrix! –