2012-03-28 33 views
7

Mã của tôi:trận Zero-chiều dài trong Java Regex

Pattern pattern = Pattern.compile("a?"); 
Matcher matcher = pattern.matcher("ababa"); 
while(matcher.find()){ 
    System.out.println(matcher.start()+"["+matcher.group()+"]"+matcher.end()); 
} 

Output:

0[a]1 
1[]1 
2[a]3 
3[]3 
4[a]5 
5[]5 

Những gì tôi biết:

  • "a" là viết tắt của số không hoặc một lần xuất hiện của ký tự 'a'.

Java API cho biết:

  • matcher.start() trả về chỉ số bắt đầu của trận đấu trước đó.
  • matcher.end() trả về giá trị bù trừ sau khi ký tự cuối cùng khớp với nhau.
  • matcher.group() trả lại kết quả đầu vào khớp với kết quả trùng khớp trước đây . Đối với một m khớp với chuỗi đầu vào, các biểu thức m.group() và s.substring (m.start(), m.end()) là tương đương. Và đối với một số mẫu, ví dụ: *, khớp với chuỗi trống. Phương thức này sẽ trả về chuỗi trống khi mẫu khớp thành công chuỗi trống trong đầu vào.

Những gì tôi muốn biết:

  1. Trong đó tình huống nào engine regex gặp một số không xảy ra một nhân vật nhất định (s) - Dưới đây cho nhân vật 'a'.
  2. Trong trường hợp đó, giá trị thực sự trả về bằng phương thức start(), kết thúc() và nhóm() trong trình ghép. Tôi đã đề cập đến những gì java API nói. Nhưng tôi không rõ ràng khi nói đến tình hình thực tế như trên.

Trả lời

10

? là một định lượng tham lam, do đó trước tiên nó sẽ cố khớp với 1 lần xuất hiện trước khi thử 0 lần xuất hiện. Trong chuỗi của bạn,

  1. nó bắt đầu bằng chữ cái đầu tiên 'a' và cố gắng khớp lại lần xuất hiện 1 lần. Chữ 'a' phù hợp và do đó nó trả về kết quả đầu tiên bạn thấy
  2. rồi nó di chuyển về phía trước và tìm dấu 'b'. Chữ 'b' char không khớp với regexp 1-lần xuất hiện của bạn, do đó, công cụ phát lại và cố gắng khớp với 0 lần xuất hiện. Kết quả là chuỗi rỗng được khớp -> bạn nhận được kết quả thứ hai của mình.
  3. sau đó nó di chuyển lên phía trước b vì không còn kết quả phù hợp nào nữa và nó bắt đầu lại với từ 'a' thứ hai của bạn.
  4. vv ... bạn sẽ có được điểm ...

Nó phức tạp hơn một chút so với nhưng đó là ý tưởng chính. Khi 1-lần xuất hiện không thể phù hợp, sau đó nó sẽ cố gắng với 0-xuất hiện.

Đối với các giá trị bắt đầu, kết thúc và nhóm, chúng sẽ là nơi bắt đầu, kết thúc và nhóm là kết quả phù hợp, vì vậy trong kết hợp 0 ​​lần xuất hiện đầu tiên của chuỗi, bạn nhận được 1, 1 và chuỗi emtpy. Tôi không chắc điều này thực sự trả lời câu hỏi của bạn.

+0

+1 đề cập đến các giải thích về hành vi lượng hóa tham lam của. Nhưng còn 5 [5] thì sao? Tại sao nó luôn thêm một sự xuất hiện 0 vào cuối mỗi chuỗi? – namalfernandolk

+0

Hãy lấy một ví dụ đơn giản hơn với chuỗi "a". Động cơ bắt đầu bằng 0 và cố gắng khớp thành công 'a' -> để so khớp đầu tiên và di chuyển forwars đến vị trí 1 -> ở vị trí 1, nó sẽ thử kết quả trùng khớp 1 lần -> vì kết thúc chuỗi. Nó vẫn có thể làm cho một trận đấu 0-xuất hiện -> thành công. Sau đó nó di chuyển về phía trước -> cuối chuỗi -> kết thúc các trận đấu –

+0

Thanx rất nhiều Guillaume. Nhưng sau khi kết hợp thành công cho 'a' Tại sao và làm thế nào nó di chuyển về phía trước. Không còn chỉ mục nữa; và không còn ký tự. Phải không? – namalfernandolk

3

iterating qua vài ví dụ sẽ rõ ràng trong các hoạt động của matcher.find() cho bạn:

Regex cơ mất trên một ký tự từ chuỗi (ví dụ Ababa) và cố gắng để tìm thấy nếu mẫu bạn đang tìm kiếm trong chuỗi có thể được tìm thấy hoặc không . Nếu mẫu tồn tại, thì (như API đã đề cập):

matcher.start() trả về chỉ mục bắt đầu, matcher.end() trả về giá trị bù trừ sau khi ký tự cuối cùng khớp.

Nếu kết quả trùng khớp không tồn tại. sau đó bắt đầu() và kết thúc() trả về cùng một chỉ mục, đó là để tuân thủ chiều dài phù hợp bằng không.

Nhìn xuống ví dụ sau đây:

 // Searching for string either "a" or "" 
     Pattern pattern = Pattern.compile("a?"); 
     Matcher matcher = pattern.matcher("abaabbbb"); 
     while(matcher.find()){ 
      System.out.println(matcher.start()+"["+matcher.group()+"]"+matcher.end()); 
     } 

Output:

0[a]1 
    1[]1 
    2[a]3 
    3[a]4 
    4[]4 
    5[]5 
    6[]6 
    7[]7 
    8[]8 


     // Searching for string either "aa" or "a" 
     Pattern pattern = Pattern.compile("aa?"); 
    Matcher matcher = pattern.matcher("abaabbbb"); 
    while(matcher.find()){ 
     System.out.println(matcher.start()+"["+matcher.group()+"]"+matcher.end()); 
    } 

Output:

0[a]1 
2[aa]4 
+0

+1 để có giải thích tốt đẹp. Bạn đang chỉ rằng "a?" là bằng nhau (ngữ nghĩa) để tìm kiếm chuỗi là "a" hoặc ""? Sau đó, bạn có thể giải thích lý do tại sao luôn có một ký tự có độ dài bằng không ở cuối chuỗi nguồn không? Ví dụ: Đối với "aaaa", nó cũng cho 4 [] 4 ở cuối cho mẫu "a?" ? – namalfernandolk

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