2012-09-21 24 views
28

Tôi đang cố gắng để thực hiện một phân chia chuỗi trên một tập hợp các dữ liệu có phần bất thường trông giống như sau:Chuỗi chia trên đường dây mới, tab và một số số lượng chỗ

\n\tName: John Smith 
\n\t Home: Anytown USA 
\n\t Phone: 555-555-555 
\n\t Other Home: Somewhere Else 
\n\t Notes: Other data 
\n\tName: Jane Smith 
\n\t Misc: Data with spaces 

Tôi muốn chuyển đổi này vào một tuple/dict mà sau này tôi sẽ chia trên dấu hai chấm :, nhưng trước tiên tôi cần phải loại bỏ tất cả khoảng trắng thừa. Tôi đoán một regex là cách tốt nhất nhưng tôi dường như không thể có được một trong đó hoạt động, dưới đây là nỗ lực của tôi.

data_string.split('\n\t *') 

Trả lời

61

Chỉ cần sử dụng .strip(), nó sẽ xóa tất cả khoảng trắng cho bạn, bao gồm các tab và dòng mới, trong khi chia nhỏ. Việc chia tách bản thân sau đó có thể được thực hiện với data_string.splitlines():

[s.strip() for s in data_string.splitlines()] 

Output:

>>> [s.strip() for s in data_string.splitlines()] 
['Name: John Smith', 'Home: Anytown USA', 'Phone: 555-555-555', 'Other Home: Somewhere Else', 'Notes: Other data', 'Name: Jane Smith', 'Misc: Data with spaces'] 

Bạn thậm chí có thể inline tách trên : cũng bây giờ:

>>> [s.strip().split(': ') for s in data_string.splitlines()] 
[['Name', 'John Smith'], ['Home', 'Anytown USA'], ['Phone', '555-555-555'], ['Other Home', 'Somewhere Else'], ['Notes', 'Other data'], ['Name', 'Jane Smith'], ['Misc', 'Data with spaces']] 
+0

Điều đó làm việc tuyệt vời, cú pháp của [List comprehension] (http://docs.python.org/tutorial/datastructures.html#list-comprehensions) không phải là điều tôi đã thấy trước đây vì vậy tôi cho rằng ' sẽ phải đọc nó. – PopeJohnPaulII

+0

hoạt động như một sự quyến rũ! tuyệt vời! cảm ơn –

0

Bạn có thể sử dụng

này
string.strip().split(":") 
5
>>> for line in s.splitlines(): 
...  line = line.strip() 
...  if not line:continue 
...  ary.append(line.split(":")) 
... 
>>> ary 
[['Name', ' John Smith'], ['Home', ' Anytown USA'], ['Misc', ' Data with spaces' 
]] 
>>> dict(ary) 
{'Home': ' Anytown USA', 'Misc': ' Data with spaces', 'Name': ' John Smith'} 
>>> 
5

Bạn có thể giết chết hai con chim với đá một regex:

>>> r = """ 
... \n\tName: John Smith 
... \n\t Home: Anytown USA 
... \n\t Phone: 555-555-555 
... \n\t Other Home: Somewhere Else 
... \n\t Notes: Other data 
... \n\tName: Jane Smith 
... \n\t Misc: Data with spaces 
... """ 
>>> import re 
>>> print re.findall(r'(\S[^:]+):\s*(.*\S)', r) 
[('Name', 'John Smith'), ('Home', 'Anytown USA'), ('Phone', '555-555-555'), ('Other Home', 'Somewhere Else'), ('Notes', 'Other data'), ('Name', 'Jane Smith'), ('Misc', 'Data with spaces')] 
>>> 
+0

+1 cho câu nói của bạn :) – Yamaneko

+0

Khá tốt, nhưng '[\ t] *' của bạn không làm gì cả; '(. +)' sẽ luôn luôn ăn khoảng trống sau nếu có. Bạn có thể làm điều này thay vào đó: '(. +?) [\ T] * $'. Bộ định lượng miễn cưỡng cho phép nó dừng sớm, trong khi '$' đảm bảo nó vẫn tiêu thụ toàn bộ dòng. –

+0

@AlanMoore: chính xác, đã chỉnh sửa bài đăng. – georg

0

Regex của là không thực sự là công cụ tốt nhất cho công việc ở đây. Như những người khác đã nói, sử dụng kết hợp str.strip()str.split() là cách để đi. Dưới đây là một lót để làm điều đó:

>>> data = '''\n\tName: John Smith 
... \n\t Home: Anytown USA 
... \n\t Phone: 555-555-555 
... \n\t Other Home: Somewhere Else 
... \n\t Notes: Other data 
... \n\tName: Jane Smith 
... \n\t Misc: Data with spaces''' 
>>> {line.strip().split(': ')[0]:line.split(': ')[1] for line in data.splitlines() if line.strip() != ''} 
{'Name': 'Jane Smith', 'Other Home': 'Somewhere Else', 'Notes': 'Other data', 'Misc': 'Data with spaces', 'Phone': '555-555-555', 'Home': 'Anytown USA'} 
3

Nếu bạn nhìn vào the documentation cho str.split:

Nếu tháng chín không được xác định hoặc là Không, một thuật toán tách khác nhau được áp dụng: chạy của khoảng trắng liên tiếp là được coi là một dấu tách đơn và kết quả sẽ không chứa các chuỗi rỗng ở đầu hoặc cuối nếu chuỗi có khoảng trắng đầu hoặc cuối. Do đó, tách một chuỗi rỗng hoặc một chuỗi bao gồm khoảng trắng chỉ với một dấu tách Không có trả về [].

Nói cách khác, nếu bạn đang cố gắng để tìm ra những gì để vượt qua để split để có được '\n\tName: Jane Smith' để ['Name:', 'Jane', 'Smith'], chỉ cần vượt qua không có gì (hoặc Không).

Điều này gần như giải quyết toàn bộ vấn đề của bạn. Có hai phần còn lại.

Trước tiên, bạn chỉ có hai trường, thứ hai trong số đó có thể chứa dấu cách. Vì vậy, bạn chỉ muốn một chia, không nhiều nhất có thể. Vì vậy:

s.split(None, 1) 

Tiếp theo, bạn vẫn có những dấu hai chấm. Nhưng bạn không cần phải phân chia chúng.Ít nhất cho dữ liệu bạn đã cho chúng ta thấy, ruột kết luôn xuất hiện ở phần cuối của trường đầu tiên, không có khoảng trống trước và luôn luôn không gian sau đó, vì vậy bạn chỉ có thể loại bỏ nó:

key, value = s.split(None, 1) 
key = key[:-1] 

Có một triệu các cách khác để làm điều này, tất nhiên; đây chỉ là một trong đó có vẻ gần nhất với những gì bạn đã cố gắng.

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