2012-01-19 35 views
26

Để chia chuỗi bằng dấu cách trong python, người ta thường sử dụng split phương pháp của chuỗi không có tham số:Python: tách chuỗi bởi tất cả các ký tự không gian

>>> 'a\tb c\nd'.split() 
['a', 'b', 'c', 'd'] 

Nhưng hôm qua tôi chạy qua một chuỗi sử dụng ZERO WIDTH SPACE giữa các từ như tốt. Sau khi quay kiến ​​thức mới của tôi trong một black magic hiệu suất ngắn (trong số folks JavaScript), tôi muốn hỏi làm thế nào để tách tốt hơn bởi tất cả whitespace characters, kể từ khi split là không đủ:

>>> u'a\u200bc d'.split() 
[u'a\u200bc', u'd'] 

UPD1

có vẻ như giải pháp được đề xuất bởi sth hoạt động bình thường nhưng phụ thuộc vào một số cài đặt hệ điều hành hoặc tùy chọn biên dịch Python. Nó sẽ được tốt đẹp để biết lý do chắc chắn (và nếu các thiết lập có thể được bật trong Windows).

UPD2 cptphil tìm thấy một link tuyệt vời mà làm cho mọi thứ rõ ràng:

Vì vậy, tôi đã liên lạc với Ủy ban kỹ thuật Unicode về vấn đề này và nhận được một phản ánh kịp thời nhận được phản hồi trở lại. Họ chỉ rằng ZWSP là, Ngày xửa ngày xưa coi khoảng trắng nhưng điều đó đã thay đổi trong Unicode 4.0.1

Một trích dẫn từ unicode site:

Thay đổi U + 200B độ rộng bằng không từ Zs đến Cf (2003.10.27)

Đã xảy ra sự cố liên tục khi sử dụng không gian chiều rộng bằng không 200 U + 200B (ZWSP). Chức năng của nhân vật này là cho phép ngắt dòng tại các vị trí mà thông thường sẽ không được phép, và do đó chức năng là một ký tự định dạng với một danh mục chung của Cf. Hành vi này cũng được ghi lại trong Tiêu chuẩn Unicode và ký tự không được coi là ký tự khoảng trắng trong Cơ sở dữ liệu ký tự Unicode. Tuy nhiên, vì lý do lịch sử, danh mục chung vẫn là Z (Dấu tách không gian), khiến nhân vật bị lạm dụng. ZWSP cũng là ký tự Zs duy nhất không phải là khoảng trắng. Danh mục chung có thể gây hiểu nhầm về quy tắc D13 Base character như cho phép ZWSP làm cơ sở cho việc kết hợp các dấu.

Đề xuất là thay đổi danh mục chung của U + 200B từ Z thành Cf.

Độ phân giải: Đã đóng. Danh mục chung của U + 200B sẽ được thay đổi từ Z thành Cf trong phiên bản Unicode 4.0.1.

Thay đổi sau đó được phản ánh bằng Python. Kết quả của u'\u200B'.isspace() trong Python 2.5.4 và 2.6.5 là True, trong Python 2.7.1 nó đã là False.

Đối với nhân vật không gian khác thường split là đủ:

>>> u'a\u200Ac'.split() 
[u'a', u'c'] 

Và nếu điều đó là không đủ cho bạn, thêm nhân vật từng người một như Gabi Purcaru gợi ý dưới đây.

+1

Trên máy tính của tôi 'u'a \ u200bc d'.split() 'trả' [u'a ' u'c', u'd' ] '. Điều này đang sử dụng Python 2.6.5 trên Ubuntu. – NPE

+1

@aix: nó trả về '[u'a \ u200bc ', u'd']' ở đây (Python 2.7.2 trên Kiến trúc Linux). Miền địa phương của Hoa Kỳ. –

+0

@aix, hmm, thú vị! – newtover

Trả lời

17

Sửa

Nó chỉ ra rằng \ u200b không phải là kỹ thuật được định nghĩa là khoảng trắng, và do đó, python không nhận ra nó là phù hợp \ s ngay cả với cờ unicode trên. Vì vậy, nó phải được coi là một ký tự không khoảng trắng.

http://en.wikipedia.org/wiki/Whitespace_character#Unicode

http://bugs.python.org/issue13391

import re 

re.split(ur"[\u200b\s]+", "some string", flags=re.UNICODE) 
+0

cảm ơn liên kết! – newtover

+0

đây là nơi '\ s' được ghi lại https://docs.python.org/2/howto/regex.html –

2

Bạn có thể sử dụng 'tái' mô-đun và vượt qua một tách để 'chia': http://docs.python.org/library/re.html#re.split

+0

Bằng cách đó tôi có thể vượt qua một dấu tách đơn, không phải là một nhóm trong số họ – newtover

+0

Điều này sẽ không giúp OP kể từ khi bạn chỉ có thể chỉ định * một * tách chuỗi, không phải là một danh sách của tất cả các ký tự khoảng trắng có thể. 'split()' với đối số 'sep' hoạt động khá khác so với không có đối số, hãy xem liên kết của bạn để biết chi tiết. –

+0

xin lỗi, tôi dán liên kết doc 'str' thay vì 're' - cố định;) –

6

Bạn có thể sử dụng một biểu thức chính quy với kích hoạt Unicode khớp:

>>> re.split(r'(?u)\s', u'a\u200bc d') 
[u'a', u'c', u'd'] 
+1

có vẻ như, bạn (và @aix) có điều gì đó trong cài đặt mà tôi không có! Tôi có nghĩa là không hoạt động trên Windows 7. – newtover

+0

mặc dù nó hoạt động trên một FreeBSD gần đó! – newtover

4

Bạn có thể sử dụng re.split, như này:

import re 
re.split(u'\s|\u200b', your_string) 
+0

Tôi không muốn đặt tên cho tất cả = ( – newtover

+0

cũng là cách tốt nhất để đi là @ sth's, nhưng nếu nó không hiệu quả với bạn, bạn có thể phải đặt tên cho tất cả (nếu, tất nhiên, bạn không tìm thấy lý do tại sao các giải pháp của họ không hoạt động) –

2

Bạn có thể sử dụng một cái gì đó như thế này?

re.split(r'\s+', your_string, re.UNICODE) 
2

Chỉ cần sử dụng split:

>>> u'\u200b'.isspace() 
True 
+0

Như bạn có thể thấy từ ví dụ trong văn bản của câu hỏi không phải lúc nào cũng hoạt động. – newtover

+0

+1 để làm cho tôi biết về phương thức 'isspace' =) – newtover

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