2010-05-25 26 views
6

Tôi cần tìm kiếm các dòng trong tệp CSV kết thúc bằng chuỗi chưa được trích dẫn, được trích dẫn kép.Regex để tìm chuỗi chưa được phân tích

Ví dụ:

1,2,a,b,"dog","rabbit 

sẽ phù hợp trong khi

1,2,a,b,"dog","rabbit","cat bird" 
1,2,a,b,"dog",rabbit 

sẽ không được.

Tôi có rất kinh nghiệm hạn chế với biểu thức thông thường, và điều duy nhất tôi có thể nghĩ đến là cái gì đó như

"[^"]*$ 

Tuy nhiên, phù hợp với trích dẫn cuối cùng để kết thúc dòng.

Điều này sẽ được thực hiện như thế nào?

+1

Điều gì về '" a \ "bc" 'hoặc' "a" "bc" '? – SLaks

+0

Giả sử không có dấu ngoặc kép" trung gian "(không có dấu ngoặc kép lồng nhau) –

Trả lời

5

Giả sử không thể thoát khỏi dấu ngoặc kép, bạn cần phải kiểm tra tính chẵn lẻ của dấu ngoặc kép (đảm bảo rằng có số chẵn của chúng thay vì lẻ). Cụm từ thông dụng phù hợp cho điều đó:

^(([^"]*"){2})*[^"]*$ 

Điều đó sẽ khớp với tất cả các dòng có số dấu ngoặc kép. Bạn có thể đảo ngược kết quả cho tất cả các chuỗi với một số lẻ. Hoặc bạn có thể chỉ cần thêm một ([^"]*") phần ngay từ đầu:

^[^"]*"(([^"]*"){2})*[^"]*$ 

Tương tự như vậy, nếu bạn có quyền truy cập vào các nhà khai thác miễn cưỡng thay vì những tham lam, bạn có thể sử dụng một biểu thức đơn giản-looking:

^((.*"){2})*.*$   #even 
^.*"((.*"){2})*.*$  #odd 

Bây giờ, nếu dấu ngoặc kép có thể được thoát, đó là một câu hỏi khác hoàn toàn, nhưng cách tiếp cận sẽ giống nhau: xác định tính chẵn lẻ của dấu ngoặc kép không thoát.

+0

Không nên có một số dấu hỏi trong hai regex cuối cùng? Nhưng tôi khuyên bạn nên Cách tiếp cận đầu tiên của bạn nên được an toàn bởi vì không một phần nào của regex có thể khớp với các ký tự giống như một phần lân cận - mọi thứ khớp với một câu trích dẫn hoặc không báo giá –

+0

@Alan: Đối với các dấu hỏi, phụ thuộc vào phương ngữ regex của bạn. Một số phương ngữ của regex sử dụng '*? 'làm Kleene clo miễn cưỡng chắc chắn trong khi những người khác yêu cầu bạn chỉ định cờ cho regex để thông báo cho người phiên dịch rằng Kleene đóng cửa miễn cưỡng. Những người khác có thể xem xét họ miễn cưỡng theo mặc định và cần phải được cho biết một cách rõ ràng là tham lam. – Welbog

+0

Tôi không biết bất kỳ hương vị regex nào xử lý định lượng như là miễn cưỡng theo mặc định. PHP có công cụ sửa đổi 'U', làm cho chúng miễn cưỡng trừ khi bạn sử dụng dấu chấm hỏi để làm cho chúng tham lam. Nhiều người, bản thân tôi trong số họ, tin rằng tính năng đó là một sai lầm, và người dùng nên được khuyến khích mạnh mẽ từ việc sử dụng nó. Bất kỳ lợi ích nào nó mang lại đều bị hủy bỏ bởi sự nhầm lẫn mà nó gây ra. –

4

Giả sử rằng các chuỗi không thể chứa ", bạn cần phải phù hợp với một chuỗi mà có một số lẻ của dấu ngoặc kép, như thế này:

([^"]*("[^"]*")?)*"

Lưu ý rằng đây là dễ bị tổn thương đến một cuộc tấn công DDOS.

Điều này sẽ khớp với số không hoặc nhiều tập hợp chạy không được kiểm soát, tiếp theo là chuỗi được trích dẫn.

+0

Tại sao nó dễ bị tổn thương bởi DDOS? –

+0

Đó là http://msdn.microsoft.com/en-us/magazine/ff646973.aspx (Câu trả lời khác cũng dễ bị tổn thương) – SLaks

0

Để tránh "expandos lồng":

egrep -v '^[^"]*("[^"]*"[^"]*)*[^"]*$' my_file 
+0

Đó vẫn là một lồng nhau expando (Một thuật ngữ tốt hơn sẽ là một sự lặp lại lồng nhau) – SLaks

+0

À, tôi đã đọc nó như là "các thứ được lồng vào nhau". – DVK

1

Hãy thử điều này một:

".+[^"](,|$) 

này phù hợp với quote (bất cứ nơi nào trong dòng), sau đó (tham lam) bởi bất cứ điều gì nhưng khác báo giá trước khi kết thúc dòng hoặc dấu phẩy.

Tác động ròng là nó sẽ chỉ khớp với các dòng có chuỗi được trích dẫn treo.

Tôi nghĩ rằng nó thậm chí còn miễn dịch với 'cuộc tấn công mở rộng lồng nhau' (chúng tôi sống trong một thế giới rất nguy hiểm ...)

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