2013-05-23 13 views
11

Sử dụng python, tôi muốn chia chuỗi sau:Python: Chia một chuỗi, sự tôn trọng và giữ gìn dấu ngoặc kép

a=foo, b=bar, c="foo, bar", d=false, e="false" 

này nên kết quả trong danh sách sau đây:

['a=foo', 'b=bar', 'c="foo, bar"', 'd=false', 'e="false'"'] 

Khi sử dụng shlex trong chế độ posix và tách với ",", đối số cho c được xử lý chính xác. Tuy nhiên, nó loại bỏ các dấu ngoặc kép. Tôi cần chúng bởi vì false không giống như "false", ví dụ.

Mã của tôi cho đến nay:

import shlex 

mystring = 'a=foo, b=bar, c="foo, bar", d=false, e="false"' 

splitter = shlex.shlex(mystring, posix=True) 
splitter.whitespace += ',' 
splitter.whitespace_split = True 
print list(splitter) # ['a=foo', 'b=bar', 'c=foo, bar', 'd=false', 'e=false'] 
+2

Có thể có (thoát) dấu ngoặc kép bên trong dấu ngoặc kép không? –

+0

Có, họ có thể (thoát bằng dấu gạch chéo ngược). – Remo

+0

Tôi tin rằng đây là bản sao của http://stackoverflow.com/a/79985/1540600, cung cấp câu trả lời vượt trội. (Sử dụng 'shlex.split()'.) – sferencik

Trả lời

19
>>> s = r'a=foo, b=bar, c="foo, bar", d=false, e="false", f="foo\", bar"' 
>>> re.findall(r'(?:[^\s,"]|"(?:\\.|[^"])*")+', s) 
['a=foo', 'b=bar', 'c="foo, bar"', 'd=false', 'e="false"', 'f="foo\\", bar"'] 
  1. Các mô hình regex "[^"]*" phù hợp với một chuỗi trích dẫn đơn giản.
  2. "(?:\\.|[^"])*" khớp với chuỗi được trích dẫn và bỏ qua dấu ngoặc kép thoát vì \\. tiêu thụ hai ký tự: dấu gạch chéo ngược và bất kỳ ký tự nào.
  3. [^\s,"] khớp với dấu cách không phân cách.
  4. Kết hợp các mẫu 2 và 3 bên trong (?: |)+ khớp với chuỗi các dấu phân tách không được phân cách và chuỗi được trích dẫn, là kết quả mong muốn.
+0

Cảm ơn bạn, hoạt động như một sự quyến rũ! – Remo

+2

giải thích cách hoạt động và tôi sẽ upvote –

+1

@JasonS Tôi đồng ý, nhưng [regex101.com] (https://regex101.com/) có phần giải thích hữu ích có thể trợ giúp, ví dụ: https: //i.imgur .com/SJMAQPI.png – blah238

0

Regex có thể giải quyết việc này một cách dễ dàng đủ:

import re 

mystring = 'a=foo, b=bar, c="foo, bar", d=false, e="false"' 

splitString = re.split(',?\s(?=\w+=)',mystring) 

Các mô hình regex đây tìm kiếm một khoảng trắng theo sau là một nhân vật từ và sau đó là một dấu bằng mà chia tách chuỗi của bạn như bạn mong muốn và duy trì bất kỳ dấu ngoặc kép.

+1

Điều này sẽ chia tách ''c =" foo, bar = "'' –

+0

Điểm công bằng. Tôi đoán đó là vấn đề với regex, viết một cái gì đó ít rõ ràng hơn dường như bắt bạn với những trường hợp bất ngờ và regex rõ ràng có thể trông khủng khiếp để đọc và hiểu những gì đang xảy ra. – ydaetskcoR