2017-08-01 19 views
5

Tôi đang tìm kiếm các từ trong chuỗi phù hợp với một mẫu cụ thể. Vấn đề là, nếu các từ là một phần của địa chỉ email, chúng sẽ bị bỏ qua.Regex - Từ kết hợp trong mẫu, ngoại trừ trong địa chỉ email

Để đơn giản hóa, mẫu của "từ thích hợp" \w+\.\w+ - một hoặc nhiều ký tự, một khoảng thời gian thực và một chuỗi ký tự khác.

Câu gây ra sự cố, ví dụ: a.a b.b:c.c [email protected].

Mục tiêu là chỉ khớp với [a.a, b.b, c.c]. Với hầu hết Regexes tôi xây dựng, e.e cũng trả về (vì tôi sử dụng một số kết hợp ranh giới từ).

Ví dụ:

>>> re.findall(r"(?:^|\s|\W)(?<[email protected])(\w+\.\w+)([email protected])\b", "a.a b.b:c.c [email protected]") ['a.a', 'b.b', 'c.c', 'e.e']

Làm thế nào tôi có thể kết hợp duy nhất trong số những từ mà không chứa "@"?

+0

thay vì cố gắng để có được một regex thông minh đi, có lẽ làm sạch chuỗi đầu tiên? dải đầu tiên \ w + @ \ w + rồi xử lý. Tôi làm rất nhiều công việc ETL với python và thường nó chỉ đơn giản là dễ dàng hơn/nhanh hơn để làm sạch thùng rác, sau đó chia/xử lý dữ liệu. – sniperd

+0

http: // www.rexegg.com/regex-best-trick.html#thetrick –

Trả lời

2

Tôi chắc chắn sẽ xóa sạch nó trước và đơn giản hóa regex.

đầu tiên chúng tôi có

words = re.split(r':|\s', "a.a b.b:c.c [email protected]") 

sau đó lọc ra những từ mà có một @ trong đó.

words = [re.search(r'^(([email protected]).)*$', word) for word in words] 
1

đúng phân tích các địa chỉ email với một regex là vô cùng khó khăn, nhưng đối với trường hợp đơn giản của bạn, với một định nghĩa đơn giản của từ ~ \w\.\w và email ~ any sequence that contains @, bạn có thể tìm regex này để làm những gì bạn cần:

>>> re.findall(r"(?:^|[:\s]+)(\w+\.\w+)(?=[:\s]+|$)", "a.a b.b:c.c [email protected]") 
['a.a', 'b.b', 'c.c'] 

Bí quyết ở đây không phải là để tập trung vào những gì có trong từ tiếp theo hoặc trước đó, nhưng trên những gì từ hiện đang bị bắt phải giống như thế.

Một mẹo khác là xác định đúng cách trình tách từ. Trước từ chúng tôi sẽ cho phép nhiều khoảng trắng, : và bắt đầu chuỗi, tiêu thụ các ký tự đó, nhưng không chụp chúng. Sau từ chúng tôi yêu cầu gần như giống nhau (ngoại trừ chuỗi kết thúc, thay vì bắt đầu), nhưng chúng tôi không tiêu thụ các ký tự đó - chúng tôi sử dụng xác nhận tra cứu.

1

Bạn có thể khớp với các chất nền giống như email với \[email protected]\S+\.\S+ và khớp và chụp mẫu của bạn với (\w+\.\w+) trong tất cả các ngữ cảnh khác. Sử dụng re.findall để chỉ trả lại những giá trị bị bắt và lọc ra các mục rỗng (họ sẽ được ở re.findall kết quả khi có một trận đấu email):

import re 
rx = r"\[email protected]\S+\.\S+|(\w+\.\w+)" 
s = "a.a b.b:c.c [email protected]" 
res = filter(None, re.findall(rx, s)) 
print(res) 
# => ['a.a', 'b.b', 'c.c'] 

Xem Python demo.

Xem regex demo.

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