Bộ định lượng python

Nhóm nguyên tử [[?>...]] và lượng từ sở hữu [

>>> ip = 'fig:mango:pineapple:guava:apples:orange'

>>> re.search[r':.*?', ip][0]
':'

>>> re.search[r':.*?apple', ip][0]
':mango:pineapple'
0,
>>> ip = 'fig:mango:pineapple:guava:apples:orange'

>>> re.search[r':.*?', ip][0]
':'

>>> re.search[r':.*?apple', ip][0]
':mango:pineapple'
1,
>>> ip = 'fig:mango:pineapple:guava:apples:orange'

>>> re.search[r':.*?', ip][0]
':'

>>> re.search[r':.*?apple', ip][0]
':mango:pineapple'
2,
>>> ip = 'fig:mango:pineapple:guava:apples:orange'

>>> re.search[r':.*?', ip][0]
':'

>>> re.search[r':.*?apple', ip][0]
':mango:pineapple'
3] hiện được hỗ trợ trong biểu thức chính quy. [Đóng góp bởi Jeffrey C. Jacobs và Serhiy Storchaka trong bpo-433030. ]

Áp phích được tạo bằng Canva

Nếu bạn không quen thuộc với các biểu thức chính quy, hãy xem Python re[gex] của tôi?


quay lui

Các bộ định lượng tham lam khớp với nhau càng nhiều càng tốt, miễn là biểu thức chính quy tổng thể được thỏa mãn. Ví dụ:

>>> ip = 'fig:mango:pineapple:guava:apples:orange'

>>> re.search[r':.*?', ip][0]
':'

>>> re.search[r':.*?apple', ip][0]
':mango:pineapple'
4 sẽ khớp với
>>> ip = 'fig:mango:pineapple:guava:apples:orange'

>>> re.search[r':.*?', ip][0]
':'

>>> re.search[r':.*?apple', ip][0]
':mango:pineapple'
5 theo sau là phần còn lại của dòng nhập. Tuy nhiên, nếu bạn thay đổi mẫu thành
>>> ip = 'fig:mango:pineapple:guava:apples:orange'

>>> re.search[r':.*?', ip][0]
':'

>>> re.search[r':.*?apple', ip][0]
':mango:pineapple'
6, phần
>>> ip = 'fig:mango:pineapple:guava:apples:orange'

>>> re.search[r':.*?', ip][0]
':'

>>> re.search[r':.*?apple', ip][0]
':mango:pineapple'
7 không thể đơn giản sử dụng phần còn lại của dòng đầu vào. Công cụ regex sẽ phải tìm phần lớn nhất sao cho
>>> ip = 'fig:mango:pineapple:guava:apples:orange'

>>> re.search[r':.*?', ip][0]
':'

>>> re.search[r':.*?apple', ip][0]
':mango:pineapple'
8 cũng là một phần của kết quả khớp [tất nhiên với điều kiện là đầu vào có chuỗi như vậy]

>>> import re

>>> ip = 'fig:mango:pineapple:guava:apples:orange'

>>> re.search[r':.*', ip][0]
':mango:pineapple:guava:apples:orange'

>>> re.search[r':.*apple', ip][0]
':mango:pineapple:guava:apple'

Đối với trường hợp

>>> ip = 'fig:mango:pineapple:guava:apples:orange'

>>> re.search[r':.*?', ip][0]
':'

>>> re.search[r':.*?apple', ip][0]
':mango:pineapple'
6, công cụ biểu thức chính quy của Python thực sự sử dụng tất cả các ký tự khi nhìn thấy
>>> ip = 'fig:mango:pineapple:guava:apples:orange'

>>> re.search[r':.*?', ip][0]
':'

>>> re.search[r':.*?apple', ip][0]
':mango:pineapple'
7. Sau đó, nhận ra rằng khớp tổng thể không thành công, nó trả về một ký tự từ cuối dòng và kiểm tra lại. Quá trình này được lặp lại cho đến khi tìm thấy kết quả phù hợp hoặc lỗi được xác nhận. Theo cách nói của biểu thức chính quy, điều này được gọi là quay lui

Kiểu khám phá này phù hợp để đáp ứng biểu thức chính quy tổng thể cũng áp dụng cho các bộ định lượng không tham lam.

$ python3.11 -q
>>> import re

>>> ip = 'fig:mango:pineapple:guava:apples:orange'

>>> re.search[r':.*+', ip][0]
':mango:pineapple:guava:apples:orange'

>>> bool[re.search[r':.*+apple', ip]]
False
1 sẽ bắt đầu bằng 0 ký tự theo sau là một, hai, ba, v.v. cho đến khi tìm thấy kết quả khớp

>>> ip = 'fig:mango:pineapple:guava:apples:orange'

>>> re.search[r':.*?', ip][0]
':'

>>> re.search[r':.*?apple', ip][0]
':mango:pineapple'

Lưu ý rằng một số công cụ regex như re2 không sử dụng quay lui


lượng từ sở hữu

Cho đến Python 3. 10, bạn phải sử dụng các lựa chọn thay thế như mô-đun regex của bên thứ ba cho các bộ định lượng sở hữu. Mô-đun

$ python3.11 -q
>>> import re

>>> ip = 'fig:mango:pineapple:guava:apples:orange'

>>> re.search[r':.*+', ip][0]
':mango:pineapple:guava:apples:orange'

>>> bool[re.search[r':.*+apple', ip]]
False
2 hỗ trợ các bộ định lượng sở hữu từ Python 3. 11 phiên bản

Sự khác biệt giữa lượng từ tham lam và sở hữu là từ sở hữu sẽ không quay lại để tìm đối sánh. Nói cách khác, lượng từ sở hữu sẽ luôn sử dụng mọi ký tự khớp với mẫu mà nó được áp dụng. Cú pháp khôn ngoan, bạn cần thêm

$ python3.11 -q
>>> import re

>>> ip = 'fig:mango:pineapple:guava:apples:orange'

>>> re.search[r':.*+', ip][0]
':mango:pineapple:guava:apples:orange'

>>> bool[re.search[r':.*+apple', ip]]
False
3 vào lượng từ tham lam để biến nó thành sở hữu, tương tự như thêm
$ python3.11 -q
>>> import re

>>> ip = 'fig:mango:pineapple:guava:apples:orange'

>>> re.search[r':.*+', ip][0]
':mango:pineapple:guava:apples:orange'

>>> bool[re.search[r':.*+apple', ip]]
False
4 cho trường hợp không tham lam

Không giống như các bộ định lượng tham lam hoặc không tham lam,

$ python3.11 -q
>>> import re

>>> ip = 'fig:mango:pineapple:guava:apples:orange'

>>> re.search[r':.*+', ip][0]
':mango:pineapple:guava:apples:orange'

>>> bool[re.search[r':.*+apple', ip]]
False
5 sẽ không bao giờ khớp, bởi vì
$ python3.11 -q
>>> import re

>>> ip = 'fig:mango:pineapple:guava:apples:orange'

>>> re.search[r':.*+', ip][0]
':mango:pineapple:guava:apples:orange'

>>> bool[re.search[r':.*+apple', ip]]
False
6 sẽ tiêu thụ phần còn lại của dòng, không còn cách nào khớp với
>>> ip = 'fig:mango:pineapple:guava:apples:orange'

>>> re.search[r':.*?', ip][0]
':'

>>> re.search[r':.*?apple', ip][0]
':mango:pineapple'
8

$ python3.11 -q
>>> import re

>>> ip = 'fig:mango:pineapple:guava:apples:orange'

>>> re.search[r':.*+', ip][0]
':mango:pineapple:guava:apples:orange'

>>> bool[re.search[r':.*+apple', ip]]
False

Đây là một ví dụ thực tế hơn. Giả sử bạn muốn so khớp các số nguyên lớn hơn hoặc bằng

$ python3.11 -q
>>> import re

>>> ip = 'fig:mango:pineapple:guava:apples:orange'

>>> re.search[r':.*+', ip][0]
':mango:pineapple:guava:apples:orange'

>>> bool[re.search[r':.*+apple', ip]]
False
8 trong đó các số này có thể tùy chọn có các số 0 đứng đầu

>>> numbers = '42 314 001 12 00984'

# this solution fails because 0* and \d{3,} can both match leading zeros
# and greedy quantifiers will give up characters to help overall regex succeed
>>> re.findall[r'0*\d{3,}', numbers]
['314', '001', '00984']

# here 0*+ will not give back leading zeros after they are consumed
>>> re.findall[r'0*+\d{3,}', numbers]
['314', '00984']

# workaround if possessive quantifiers are not supported
>>> re.findall[r'0*[1-9]\d{2,}', numbers]
['314', '00984']

Đây là một ví dụ khác. Mục tiêu là khớp các dòng có ký tự không phải khoảng trắng đầu tiên không phải là ký tự

$ python3.11 -q
>>> import re

>>> ip = 'fig:mango:pineapple:guava:apples:orange'

>>> re.search[r':.*+', ip][0]
':mango:pineapple:guava:apples:orange'

>>> bool[re.search[r':.*+apple', ip]]
False
9. Một dòng phù hợp phải có ít nhất một ký tự không phải ____12_______9, vì vậy các dòng trống và những dòng chỉ có ký tự khoảng trắng không được khớp

>>> lines = ['#comment', 'c = "#"', '\t #comment', 'abc', '', ' \t ']

# this solution fails because \s* can backtrack
# and [^#] can match a whitespace character as well
>>> [e for e in lines if re.match[r'\s*[^#]', e]]
['c = "#"', '\t #comment', 'abc', ' \t ']

# this works because \s*+ will not give back any whitespace characters
>>> [e for e in lines if re.match[r'\s*+[^#]', e]]
['c = "#"', 'abc']

# workaround if possessive quantifiers are not supported
>>> [e for e in lines if re.match[r'\s*[^#\s]', e]]
['c = "#"', 'abc']


nhóm nguyên tử

>>> numbers = '42 314 001 12 00984'

# this solution fails because 0* and \d{3,} can both match leading zeros
# and greedy quantifiers will give up characters to help overall regex succeed
>>> re.findall[r'0*\d{3,}', numbers]
['314', '001', '00984']

# here 0*+ will not give back leading zeros after they are consumed
>>> re.findall[r'0*+\d{3,}', numbers]
['314', '00984']

# workaround if possessive quantifiers are not supported
>>> re.findall[r'0*[1-9]\d{2,}', numbers]
['314', '00984']
1 là một nhóm nguyên tử, trong đó
>>> numbers = '42 314 001 12 00984'

# this solution fails because 0* and \d{3,} can both match leading zeros
# and greedy quantifiers will give up characters to help overall regex succeed
>>> re.findall[r'0*\d{3,}', numbers]
['314', '001', '00984']

# here 0*+ will not give back leading zeros after they are consumed
>>> re.findall[r'0*+\d{3,}', numbers]
['314', '00984']

# workaround if possessive quantifiers are not supported
>>> re.findall[r'0*[1-9]\d{2,}', numbers]
['314', '00984']
2 là mẫu bạn muốn bảo vệ khỏi việc quay lui thêm bằng cách cách ly nó khỏi các phần khác của biểu thức chính quy

Đây là một ví dụ với bộ định lượng tham lam

>>> numbers = '42 314 001 12 00984'

# 0* is greedy and the [?>] grouping prevents backtracking
# same as: re.findall[r'0*+\d{3,}', numbers]
>>> re.findall[r'[?>0*]\d{3,}', numbers]
['314', '00984']

Đây là một ví dụ với bộ định lượng không tham lam

>>> ip = 'fig::mango::pineapple::guava::apples::orange'

# this matches from the first '::' to the first occurrence of '::apple'
>>> re.search[r'::.*?::apple', ip][0]
'::mango::pineapple::guava::apple'

# '[?>::.*?::]' will match only from '::' to the very next '::'
# '::mango::' fails because 'apple' isn't found afterwards
# similarly '::pineapple::' fails
# '::guava::' succeeds because it is followed by 'apple'
>>> re.search[r'[?>::.*?::]apple', ip][0]
'::guava::apple'

Mô-đun regex có cờ

>>> numbers = '42 314 001 12 00984'

# this solution fails because 0* and \d{3,} can both match leading zeros
# and greedy quantifiers will give up characters to help overall regex succeed
>>> re.findall[r'0*\d{3,}', numbers]
['314', '001', '00984']

# here 0*+ will not give back leading zeros after they are consumed
>>> re.findall[r'0*+\d{3,}', numbers]
['314', '00984']

# workaround if possessive quantifiers are not supported
>>> re.findall[r'0*[1-9]\d{2,}', numbers]
['314', '00984']
3 để khớp từ phải sang trái làm cho nó phù hợp hơn so với nhóm nguyên tử trong một số trường hợp nhất định

>>> import regex

>>> ip = 'fig::mango::pineapple::guava::apples::orange'
>>> regex.search[r'[?r]::.*?::apple', ip][0]
'::guava::apple'

# this won't be possible with just atomic grouping
>>> ip = 'and this book is good and those are okay and that movie is bad'
>>> regex.search[r'[?r]th.*?\bis bad', ip][0]
'that movie is bad'

Quay lui thảm khốc

Quay lui có thể trở nên tốn thời gian đáng kể đối với một số trường hợp góc nhất định. Đó là lý do tại sao một số công cụ regex không sử dụng chúng, với chi phí không hỗ trợ một số tính năng như giao diện. Nếu ứng dụng của bạn chấp nhận biểu thức chính quy do người dùng xác định, bạn có thể cần phải bảo vệ chống lại các mẫu thảm họa như vậy. từ wikipedia. làm lại

Từ chối dịch vụ biểu thức chính quy [ReDoS] là một cuộc tấn công phức tạp về thuật toán tạo ra từ chối dịch vụ bằng cách cung cấp biểu thức chính quy và/hoặc đầu vào mất nhiều thời gian để đánh giá. Cuộc tấn công khai thác thực tế là nhiều triển khai biểu thức chính quy có độ phức tạp trong trường hợp xấu nhất siêu tuyến tính; . Do đó, kẻ tấn công có thể khiến chương trình tiêu tốn thời gian đáng kể bằng cách cung cấp biểu thức chính quy và/hoặc đầu vào được chế tạo đặc biệt. Chương trình sau đó sẽ chậm lại hoặc không phản hồi

Đây là một ví dụ

>>> from timeit import timeit

>>> greedy = re.compile[r'[a+|\w+]*:']
>>> possessive = re.compile[r'[a+|\w+]*+:']

# string that'll match the above patterns
>>> s1 = 'aaaaaaaaaaaaaaaa:123'
# string that does NOT match the above patterns
>>> s2 = 'aaaaaaaaaaaaaaaa-123'

# no issues when input string has a match
>>> timeit['greedy.search[s1]', number=10000, globals=globals[]]
0.016464739997900324
>>> timeit['possessive.search[s1]', number=10000, globals=globals[]]
0.016358205997676123

# if input doesn't match, greedy version suffers from catastrophic backtracking
# note that 'number' parameter is reduced to 10 since it takes a long time
>>> timeit['greedy.search[s2]', number=10, globals=globals[]]
53.71723825200024
>>> timeit['possessive.search[s2]', number=10, globals=globals[]]
0.00019008600065717474

>>> numbers = '42 314 001 12 00984'

# this solution fails because 0* and \d{3,} can both match leading zeros
# and greedy quantifiers will give up characters to help overall regex succeed
>>> re.findall[r'0*\d{3,}', numbers]
['314', '001', '00984']

# here 0*+ will not give back leading zeros after they are consumed
>>> re.findall[r'0*+\d{3,}', numbers]
['314', '00984']

# workaround if possessive quantifiers are not supported
>>> re.findall[r'0*[1-9]\d{2,}', numbers]
['314', '00984']
4 là một mẫu biểu thức chính quy ngớ ngẩn, vì nó có thể được viết lại thành
>>> numbers = '42 314 001 12 00984'

# this solution fails because 0* and \d{3,} can both match leading zeros
# and greedy quantifiers will give up characters to help overall regex succeed
>>> re.findall[r'0*\d{3,}', numbers]
['314', '001', '00984']

# here 0*+ will not give back leading zeros after they are consumed
>>> re.findall[r'0*+\d{3,}', numbers]
['314', '00984']

# workaround if possessive quantifiers are not supported
>>> re.findall[r'0*[1-9]\d{2,}', numbers]
['314', '00984']
5 sẽ không bị quay lui thảm khốc. Nhưng ví dụ này cho thấy cách các bộ định lượng được áp dụng cho một nhóm có nhiều lựa chọn thay thế bằng cách sử dụng các bộ định lượng có thể dẫn đến kết quả bùng nổ. Bạn có thể tìm thấy nhiều mô hình và chiến lược giảm thiểu như vậy trong các liên kết sau

Chủ Đề