2010-08-25 35 views
5

Tôi có chuỗi này ở đây:Có regex bỏ qua dòng mới và chỉ phù hợp trên một chuỗi lớn?

CREATE UNIQUE INDEX index555 ON 
SOME_TABLE 
(
    SOME_PK   ASC 
); 

Tôi muốn để phù hợp trên nhiều dòng và phù hợp với câu lệnh SQL (tất cả trong số họ, sẽ có nhiều người trong 1 chuỗi lớn) ... một cái gì đó như thế này, tuy nhiên tôi chỉ nhận được một trận đấu trên CREATE UNIQUE INDEX index555 ON

(CREATE\s.+;) 

lưu ý: tôi cố gắng để thực hiện điều này trong java nếu vấn đề.

Trả lời

13

Bạn cần phải sử dụng DOTALL và cờ MULTILINE khi soạn thảo một biểu thức chính quy. Dưới đây là một ví dụ mã Java:

import java.util.regex.*; 

public class test 
{ 
    public static void main(String[] args) 
    { 
     String s = 
     "CREATE UNIQUE INDEX index555 ON\nSOME_TABLE\n(\n SOME_PK   ASC\n);\nCREATE UNIQUE INDEX index666 ON\nOTHER_TABLE\n(\n OTHER_PK   ASC\n);\n"; 

     Pattern p = Pattern.compile("([^;]*?('.*?')?)*?;\\s*", Pattern.CASE_INSENSITIVE | Pattern.DOTALL | Pattern.MULTILINE); 

     Matcher m = p.matcher(s); 

     while (m.find()) 
     { 
     System.out.println ("--- Statement ---"); 
     System.out.println (m.group()); 
     } 
    } 
} 

Kết quả sẽ là:

--- Statement --- 
CREATE UNIQUE INDEX index555 ON 
SOME_TABLE 
(
    SOME_PK   ASC 
); 

--- Statement --- 
CREATE UNIQUE INDEX index666 ON 
OTHER_TABLE 
(
    OTHER_PK   ASC 
); 
3

Kiểm tra các cờ khác nhau có thể được chuyển đến Pattern.compile. Tôi nghĩ DOTALL là thứ bạn cần.

8

Kiểm tra this

Các biểu hiện thường xuyên. phù hợp với bất kỳ ký tự ngoại trừ một dòng terminator trừ cờ DOTALL được quy định

Vì vậy, bạn cần phải làm điều gì đó như thế này

Pattern p = Pattern.compile("your pattern", Pattern.DOTALL); 
5

Cờ DOTALL cho phép người . newlines trận đấu, nhưng nếu bạn chỉ đơn giản là áp dụng nó vào regex hiện tại của bạn, bạn sẽ kết thúc phù hợp với mọi thứ từ CREATE đầu tiên đến ; cuối cùng trong một lần. Nếu bạn muốn kết hợp các câu lệnh riêng lẻ, bạn sẽ cần phải làm nhiều hơn. Một lựa chọn là sử dụng một lượng hóa phi tham lam:

Pattern p = Pattern.compile("^CREATE\\b.+?;", 
    Pattern.DOTALL | Pattern.MULTILINE | Pattern.CASE_INSENSITIVE); 

Tôi cũng sử dụng MULTILINE cờ để cho các trận đấu ^ neo sau dòng mới, và CASE_INSENSITIVE vì SQL được - ít nhất, mỗi hương vị tôi đã nghe nói về . Lưu ý rằng cả ba lá cờ có "inline" hình thức mà bạn có thể sử dụng trong regex bản thân:

Pattern p = Pattern.compile("(?smi)^CREATE\\b.+?;"); 

(Hình thức inline của DOTALLs vì những lý do lịch sử, nó được gọi là "single-line" chế độ trong Perl, . nơi nó có nguồn gốc) một lựa chọn khác là sử dụng một lớp nhân vật phủ nhận:

Pattern p = Pattern.compile("(?mi)^CREATE\\b[^;]+;"); 

[^;]+ trận đấu một hoặc nhiều của bất kỳ nhân vật ngoại trừ ; --that bao gồm dòng mới, vì vậy cờ s là không cần thiết.

Cho đến giờ, tôi đã giả định rằng mọi câu lệnh đều bắt đầu ở đầu dòng và kết thúc bằng dấu chấm phẩy, như trong ví dụ của bạn. Tôi không nghĩ rằng một trong những điều đó là bắt buộc bởi các tiêu chuẩn SQL, nhưng tôi hy vọng bạn sẽ biết nếu bạn có thể đếm trên chúng trong trường hợp này.Bạn có thể muốn bắt đầu phù hợp tại một ranh giới từ thay vì một ranh giới dòng:

Pattern p = Pattern.compile("(?i)\\bCREATE\\b[^;]+;"); 

Cuối cùng, nếu bạn đang suy nghĩ về bất cứ điều gì làm phức tạp hơn với regexes và SQL, không. Phân tích cú pháp SQL với regexes là trò chơi của kẻ ngốc - nó thậm chí còn tệ hơn cả HTML và regex.

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