2013-06-24 34 views
5

Tôi đang cố gắng lấy bất kỳ văn bản nào bên ngoài dấu ngoặc vuông bằng regex.regex để lấy tất cả văn bản bên ngoài dấu ngoặc đơn

Ví dụ chuỗi

Josie Smith [3996 TRƯỜNG CAO ĐẲNG AVENUE, SOMETOWN, MD 21.003] Mugsy Chó Smith [2560 OAK ST, GLENMEADE, WI 14.098]

Tôi có thể để nhận được văn bản bên trong dấu ngoặc vuông thành công với:

addrs = re.findall(r"\[(.*?)\]", example_str) 
print addrs 
[u'3996 COLLEGE AVENUE, SOMETOWN, MD 21003',u'2560 OAK ST, GLENMEADE, WI 14098']  

nhưng tôi gặp sự cố khi nhận bất kỳ thứ gì bên ngoài trong số các dấu ngoặc vuông. Tôi đã thử một cái gì đó như sau:

names = re.findall(r"(.*?)\[.*\]+", example_str) 

nhưng mà chỉ thấy tên đầu tiên:

print names 
[u'Josie Smith '] 

Cho đến nay tôi đã chỉ nhìn thấy một chuỗi chứa 1-2 name [address] combo, nhưng tôi m giả sử có thể có bất kỳ số nào trong số chúng trong một chuỗi.

+1

các ngoặc vuông có thể được lồng nhau – aaronman

+0

@aaronman Tôi giả định rằng sẽ KHÔNG có bất kỳ dấu ngoặc ôm nào. câu hỏi hay. – Banjer

Trả lời

7

Nếu không có dấu ngoặc lồng nhau , bạn chỉ có thể làm điều này:

re.findall(r'(.*?)\[.*?\]', example_str) 

Tuy nhiên, bạn thậm chí không thực sự cần một regex ông lại. Chỉ cần chia trên dấu ngoặc:

(s.split(']')[-1] for s in example_str.split('[')) 

Lý do duy nhất nỗ lực của bạn không làm việc:

re.findall(r"(.*?)\[.*\]+", example_str) 

... là bạn đang làm một trận đấu không tham lam trong dấu ngoặc, có nghĩa là nó đã chụp tất cả mọi thứ từ khung mở đầu tiên đến khung đóng gần nhất, thay vì chỉ chụp cặp dấu ngoặc đầu tiên.


Ngoài ra, + cuối cùng có vẻ sai. Nếu bạn có 'abc [def][ghi] jkl[mno]', bạn có muốn quay lại ['abc ', '', ' jkl'] hoặc ['abc ', ' jkl'] không? Nếu trước đây, không thêm +. Nếu đó là thứ hai, hãy làm - nhưng sau đó bạn cần phải đặt toàn bộ mẫu được đặt trong một nhóm không chụp: r'(.*?)(?:\[.*?\])+.


Nếu có thể có văn bản bổ sung sau khung cuối cùng, phương pháp split sẽ làm việc tốt, hoặc bạn có thể sử dụng re.split thay vì re.findall ... nhưng nếu bạn muốn điều chỉnh regex ban đầu của bạn để làm việc với điều đó, bạn có thể .

Bằng tiếng Anh, những gì bạn muốn là bất kỳ chuỗi con nào (không tham lam) trước chuỗi con đính kèm ngoặc đơn hoặc kết thúc chuỗi, phải không?

Vì vậy, bạn cần thay đổi giữa \[.*?\]$. Tất nhiên bạn cần phải nhóm đó để viết luân phiên, và bạn không muốn nắm bắt nhóm. Vì vậy:

re.findall(r"(.*?)(?:\[.*?\]|$)", example_str) 
+0

Điều gì sẽ xảy ra nếu có bất kỳ văn bản nào * sau * cặp dấu ngoặc cuối cùng? (chỉ đề cập đến regex của bạn; giải pháp tách của bạn hoạt động) –

+0

Ah vâng, tất cả đều có ý nghĩa. Tôi thích giải pháp 'split' tốt hơn. – Banjer

+0

@TimPietzcker: Bạn có thể thêm nó theo cùng kiểu với regex gốc của OP; chút phức tạp là cách rõ ràng để viết nó cần một nhóm không bắt giữ. Đã chỉnh sửa câu trả lời để hiển thị như thế nào. – abarnert

1

bạn có thể làm điều này:

outside = re.findall(r"[^[]+(?=\[[^]]*]|$)", example_str) 

Nói cách khác: Tất cả những gì không phải là một dấu ngoặc vuông mở tiếp theo một cái gì đó bên trong dấu ngoặc vuông hoặc cuối của chuỗi

3

Nếu có dấu ngoặc bao giờ lồng nhau:

([^[\]]+)(?:$|\[) 

Ví dụ:

>>> import re 
>>> s = 'Josie Smith [3996 COLLEGE AVENUE, SOMETOWN, MD 21003]Mugsy Dog Smith [2560 OAK ST, GLENMEADE, WI 14098]' 
>>> re.findall(r'([^[\]]+)(?:$|\[)', s) 
['Josie Smith ', 'Mugsy Dog Smith '] 

Giải thích:

([^[\]]+) # match one or more characters that are not '[' or ']' and place in group 1 
(?:$|\[) # match either a '[' or at the end of the string, do not capture 
+0

Cái này hoạt động tốt hơn vì nó không trả về một chuỗi rỗng như @ abamert's –

1

Nếu bạn muốn đi với regex và vẫn xử lý các dấu ngoặc lồng nhau, bạn có thể đi với:

import re 
expr = re.compile("(?:^|])([^[\]]+)(?:\[|$)") 

print(expr.findall("myexpr[skip this[and this]]another[and skip that too]")) 

Điều này sẽ mang lại ['myexpr', 'another'].

Ý tưởng là đối sánh mọi thứ giữa việc bắt đầu chuỗi hoặc ] và cuối chuỗi hoặc [.

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