Hướng dẫn python match operator - toán tử đối sánh python

Tác giả

SÁNG. Kuchling@amk.ca>

trừu tượng

Tài liệu này là một hướng dẫn giới thiệu để sử dụng các biểu thức chính quy trong Python với mô -đun

>>> p.match("")
>>> print(p.match(""))
None
5. Nó cung cấp một giới thiệu nhẹ nhàng hơn phần tương ứng trong tài liệu tham khảo thư viện.

Giới thiệu¶

Các biểu thức chính quy (được gọi là RES, hoặc các mẫu Regexes hoặc Regex) về cơ bản là một ngôn ngữ lập trình nhỏ, chuyên dụng cao được nhúng bên trong Python và được cung cấp thông qua mô -đun

>>> p.match("")
>>> print(p.match(""))
None
5. Sử dụng ngôn ngữ nhỏ này, bạn chỉ định các quy tắc cho tập hợp các chuỗi có thể mà bạn muốn khớp; Bộ này có thể chứa các câu tiếng Anh hoặc địa chỉ e-mail hoặc lệnh tex hoặc bất cứ điều gì bạn thích. Sau đó, bạn có thể đặt câu hỏi như là chuỗi này có phù hợp với mẫu không? Bạn cũng có thể sử dụng RES để sửa đổi một chuỗi hoặc để tách nó ra theo nhiều cách khác nhau.

Các mẫu biểu thức chính quy được biên dịch thành một loạt các byte sau đó được thực hiện bởi một công cụ phù hợp được viết bằng C. Để sử dụng nâng cao, có thể cần phải chú ý cẩn thận đến cách động cơ sẽ thực hiện một RE đã cho và viết RE trong A Cách nhất định để sản xuất mã byte chạy nhanh hơn. Tối ưu hóa không được đề cập trong tài liệu này, bởi vì nó đòi hỏi bạn phải hiểu rõ về nội bộ động cơ phù hợp.

Ngôn ngữ biểu thức chính quy tương đối nhỏ và bị hạn chế, vì vậy không phải tất cả các tác vụ xử lý chuỗi có thể có thể được thực hiện bằng cách sử dụng các biểu thức thông thường. Ngoài ra còn có các nhiệm vụ có thể được thực hiện với các biểu thức thông thường, nhưng các biểu thức hóa ra rất phức tạp. Trong những trường hợp này, bạn có thể tốt hơn khi viết mã Python để thực hiện xử lý; Mặc dù mã Python sẽ chậm hơn một biểu thức thông thường phức tạp, nhưng nó cũng có thể dễ hiểu hơn.

Các mẫu đơn giản

Chúng tôi sẽ bắt đầu bằng cách tìm hiểu về các biểu thức chính quy đơn giản nhất có thể. Vì các biểu thức thông thường được sử dụng để hoạt động trên các chuỗi, chúng tôi sẽ bắt đầu với nhiệm vụ phổ biến nhất: các ký tự phù hợp.

Để giải thích chi tiết về khoa học máy tính theo các biểu thức thường xuyên (tự động tự nhiên xác định và không xác định), bạn có thể tham khảo hầu hết mọi cuốn sách giáo khoa về viết trình biên dịch.

Các ký tự phù hợp

Hầu hết các chữ cái và ký tự sẽ đơn giản phù hợp với chính họ. Ví dụ: biểu thức thông thường

>>> p.match("")
>>> print(p.match(""))
None
7 sẽ khớp chính xác với chuỗi
>>> p.match("")
>>> print(p.match(""))
None
7. .

Có những trường hợp ngoại lệ cho quy tắc này; Một số nhân vật là những người metacharacters đặc biệt, và don lồng phù hợp với chính họ. Thay vào đó, họ báo hiệu rằng một số điều ngoài tầm thường nên được khớp hoặc chúng ảnh hưởng đến các phần khác của RE bằng cách lặp lại chúng hoặc thay đổi ý nghĩa của chúng. Phần lớn tài liệu này được dành để thảo luận về các metacharacters khác nhau và những gì họ làm.

Ở đây, một danh sách đầy đủ các metacharacters; Ý nghĩa của chúng sẽ được thảo luận trong phần còn lại của howto này.

. ^ $ * + ? { } [ ] \ | ( )

Các metacharacters đầu tiên mà chúng tôi sẽ xem xét là

>>> m = p.match('tempo')
>>> m

1 và
>>> m = p.match('tempo')
>>> m

2. Chúng được sử dụng để chỉ định một lớp ký tự, đó là một tập hợp các ký tự mà bạn muốn phù hợp. Các ký tự có thể được liệt kê riêng lẻ hoặc một loạt các ký tự có thể được chỉ định bằng cách đưa hai ký tự và tách chúng bằng
>>> m = p.match('tempo')
>>> m

3. Ví dụ:
>>> m = p.match('tempo')
>>> m

4 sẽ khớp với bất kỳ ký tự nào
>>> m = p.match('tempo')
>>> m

5,
>>> m = p.match('tempo')
>>> m

6 hoặc
>>> m = p.match('tempo')
>>> m

7; Điều này giống như
>>> m = p.match('tempo')
>>> m

8, sử dụng một phạm vi để thể hiện cùng một tập hợp các ký tự. Nếu bạn chỉ muốn khớp với các chữ cái viết thường, RE của bạn sẽ là
>>> m = p.match('tempo')
>>> m

9.

Metacharacters (trừ

>>> m.group()
'tempo'
>>> m.start(), m.end()
(0, 5)
>>> m.span()
(0, 5)
0) không hoạt động trong các lớp. Ví dụ:
>>> m.group()
'tempo'
>>> m.start(), m.end()
(0, 5)
>>> m.span()
(0, 5)
1 sẽ khớp với bất kỳ ký tự nào
>>> m.group()
'tempo'
>>> m.start(), m.end()
(0, 5)
>>> m.span()
(0, 5)
2,
>>> m.group()
'tempo'
>>> m.start(), m.end()
(0, 5)
>>> m.span()
(0, 5)
3,
>>> m.group()
'tempo'
>>> m.start(), m.end()
(0, 5)
>>> m.span()
(0, 5)
4 hoặc
>>> m.group()
'tempo'
>>> m.start(), m.end()
(0, 5)
>>> m.span()
(0, 5)
5;
>>> m.group()
'tempo'
>>> m.start(), m.end()
(0, 5)
>>> m.span()
(0, 5)
5 thường là một metacharacter, nhưng bên trong một lớp nhân vật, nó đã tước bỏ bản chất đặc biệt của nó.

Bạn có thể khớp các ký tự không được liệt kê trong lớp bằng cách bổ sung cho tập hợp. Điều này được biểu thị bằng cách bao gồm một

>>> m.group()
'tempo'
>>> m.start(), m.end()
(0, 5)
>>> m.span()
(0, 5)
7 là nhân vật đầu tiên của lớp. Ví dụ:
>>> m.group()
'tempo'
>>> m.start(), m.end()
(0, 5)
>>> m.span()
(0, 5)
8 sẽ khớp với bất kỳ ký tự nào ngoại trừ
>>> m.group()
'tempo'
>>> m.start(), m.end()
(0, 5)
>>> m.span()
(0, 5)
9. Nếu Caret xuất hiện ở nơi khác trong một lớp nhân vật, nó không có ý nghĩa đặc biệt. Ví dụ:
>>> print(p.match('::: message'))
None
>>> m = p.search('::: message'); print(m)

>>> m.group()
'message'
>>> m.span()
(4, 11)
0 sẽ khớp với
>>> m.group()
'tempo'
>>> m.start(), m.end()
(0, 5)
>>> m.span()
(0, 5)
9 hoặc
>>> m.group()
'tempo'
>>> m.start(), m.end()
(0, 5)
>>> m.span()
(0, 5)
7.

Có lẽ metacharacter quan trọng nhất là dấu gạch chéo ngược,

>>> m.group()
'tempo'
>>> m.start(), m.end()
(0, 5)
>>> m.span()
(0, 5)
0. Như trong Python String Ligenals, dấu gạch chéo ngược có thể được theo sau bởi các ký tự khác nhau để báo hiệu các chuỗi đặc biệt khác nhau. Nó cũng được sử dụng để thoát khỏi tất cả các metacharacters để bạn vẫn có thể kết hợp chúng theo các mẫu; Ví dụ: nếu bạn cần khớp với
>>> m = p.match('tempo')
>>> m

1 hoặc
>>> m.group()
'tempo'
>>> m.start(), m.end()
(0, 5)
>>> m.span()
(0, 5)
0, bạn có thể đi trước chúng bằng một dấu gạch chéo ngược để loại bỏ ý nghĩa đặc biệt của chúng:
>>> print(p.match('::: message'))
None
>>> m = p.search('::: message'); print(m)

>>> m.group()
'message'
>>> m.span()
(4, 11)
6 hoặc
>>> print(p.match('::: message'))
None
>>> m = p.search('::: message'); print(m)

>>> m.group()
'message'
>>> m.span()
(4, 11)
7.

Một số chuỗi đặc biệt bắt đầu bằng

>>> print(p.match('::: message'))
None
>>> m = p.search('::: message'); print(m)

>>> m.group()
'message'
>>> m.span()
(4, 11)
8 đại diện cho các bộ ký tự được xác định trước thường hữu ích, chẳng hạn như tập hợp các chữ số, tập hợp các chữ cái hoặc tập hợp bất cứ thứ gì là khoảng trắng.

Hãy để lấy một ví dụ:

>>> print(p.match('::: message'))
None
>>> m = p.search('::: message'); print(m)

>>> m.group()
'message'
>>> m.span()
(4, 11)
9 khớp với bất kỳ ký tự chữ và số nào. Nếu mẫu regex được thể hiện bằng byte, thì điều này tương đương với lớp
p = re.compile( ... )
m = p.match( 'string goes here' )
if m:
    print('Match found: ', m.group())
else:
    print('No match')
0. Nếu mẫu regex là một chuỗi,
>>> print(p.match('::: message'))
None
>>> m = p.search('::: message'); print(m)

>>> m.group()
'message'
>>> m.span()
(4, 11)
9 sẽ khớp với tất cả các ký tự được đánh dấu là các chữ cái trong cơ sở dữ liệu Unicode được cung cấp bởi mô -đun
p = re.compile( ... )
m = p.match( 'string goes here' )
if m:
    print('Match found: ', m.group())
else:
    print('No match')
2. Bạn có thể sử dụng định nghĩa hạn chế hơn của
>>> print(p.match('::: message'))
None
>>> m = p.search('::: message'); print(m)

>>> m.group()
'message'
>>> m.span()
(4, 11)
9 trong một mẫu chuỗi bằng cách cung cấp cờ
p = re.compile( ... )
m = p.match( 'string goes here' )
if m:
    print('Match found: ', m.group())
else:
    print('No match')
4 khi biên dịch biểu thức thông thường.

Danh sách sau đây các chuỗi đặc biệt là hoàn thành. Để biết danh sách đầy đủ các chuỗi và các định nghĩa lớp mở rộng cho các mẫu chuỗi Unicode, hãy xem phần cuối cùng của cú pháp biểu thức chính quy trong tham chiếu thư viện tiêu chuẩn. Nói chung, các phiên bản Unicode phù hợp với bất kỳ ký tự nào mà trong danh mục thích hợp trong cơ sở dữ liệu Unicode.Regular Expression Syntax in the Standard Library reference. In general, the Unicode versions match any character that’s in the appropriate category in the Unicode database.

p = re.compile( ... )
m = p.match( 'string goes here' )
if m:
    print('Match found: ', m.group())
else:
    print('No match')
5

Phù hợp với bất kỳ chữ số thập phân; Điều này tương đương với lớp

p = re.compile( ... )
m = p.match( 'string goes here' )
if m:
    print('Match found: ', m.group())
else:
    print('No match')
6.

p = re.compile( ... )
m = p.match( 'string goes here' )
if m:
    print('Match found: ', m.group())
else:
    print('No match')
7

Khớp với bất kỳ ký tự không chữ số nào; Điều này tương đương với lớp

p = re.compile( ... )
m = p.match( 'string goes here' )
if m:
    print('Match found: ', m.group())
else:
    print('No match')
8.

p = re.compile( ... )
m = p.match( 'string goes here' )
if m:
    print('Match found: ', m.group())
else:
    print('No match')
9

Phù hợp với bất kỳ ký tự khoảng trắng nào; Điều này tương đương với lớp

>>> p = re.compile(r'\d+')
>>> p.findall('12 drummers drumming, 11 pipers piping, 10 lords a-leaping')
['12', '11', '10']
0.

>>> p = re.compile(r'\d+')
>>> p.findall('12 drummers drumming, 11 pipers piping, 10 lords a-leaping')
['12', '11', '10']
1

Phù hợp với bất kỳ ký tự không phải là màu sắc nào; Điều này tương đương với lớp

>>> p = re.compile(r'\d+')
>>> p.findall('12 drummers drumming, 11 pipers piping, 10 lords a-leaping')
['12', '11', '10']
2.

>>> print(p.match('::: message'))
None
>>> m = p.search('::: message'); print(m)

>>> m.group()
'message'
>>> m.span()
(4, 11)
9

Phù hợp với bất kỳ ký tự chữ và số nào; Điều này tương đương với lớp

p = re.compile( ... )
m = p.match( 'string goes here' )
if m:
    print('Match found: ', m.group())
else:
    print('No match')
0.

>>> p = re.compile(r'\d+')
>>> p.findall('12 drummers drumming, 11 pipers piping, 10 lords a-leaping')
['12', '11', '10']
5

Phù hợp với bất kỳ ký tự không phải là đồngumeric; Điều này tương đương với lớp

>>> p = re.compile(r'\d+')
>>> p.findall('12 drummers drumming, 11 pipers piping, 10 lords a-leaping')
['12', '11', '10']
6.

Các chuỗi này có thể được bao gồm bên trong một lớp ký tự. Ví dụ:

>>> p = re.compile(r'\d+')
>>> p.findall('12 drummers drumming, 11 pipers piping, 10 lords a-leaping')
['12', '11', '10']
7 là một lớp ký tự sẽ phù hợp với bất kỳ ký tự khoảng trắng nào hoặc
>>> p = re.compile(r'\d+')
>>> p.findall('12 drummers drumming, 11 pipers piping, 10 lords a-leaping')
['12', '11', '10']
8 hoặc
>>> p = re.compile(r'\d+')
>>> p.findall('12 drummers drumming, 11 pipers piping, 10 lords a-leaping')
['12', '11', '10']
9.

Metacharacter cuối cùng trong phần này là

>>> import re
>>> p = re.compile('ab*')
>>> p
re.compile('ab*')
00. Nó phù hợp với bất cứ điều gì ngoại trừ một ký tự mới và có một chế độ thay thế (
>>> import re
>>> p = re.compile('ab*')
>>> p
re.compile('ab*')
01) nơi nó sẽ phù hợp với ngay cả một dòng mới.
>>> import re
>>> p = re.compile('ab*')
>>> p
re.compile('ab*')
00 thường được sử dụng ở nơi bạn muốn khớp với bất kỳ nhân vật nào.

Lặp lại mọi thứ

Có thể khớp với các bộ ký tự khác nhau là điều đầu tiên các biểu thức chính quy có thể làm điều đó là có thể với các phương thức có sẵn trên các chuỗi. Tuy nhiên, nếu đó là khả năng bổ sung duy nhất của Regexes, thì họ sẽ không phải là một tiến bộ. Một khả năng khác là bạn có thể chỉ định rằng các phần của RE phải được lặp lại một số lần nhất định.

Metacharacter đầu tiên để lặp lại những thứ mà chúng tôi sẽ xem xét là

>>> import re
>>> p = re.compile('ab*')
>>> p
re.compile('ab*')
03.
>>> import re
>>> p = re.compile('ab*')
>>> p
re.compile('ab*')
03 không phù hợp với ký tự theo nghĩa đen
>>> import re
>>> p = re.compile('ab*')
>>> p
re.compile('ab*')
05; Thay vào đó, nó chỉ định rằng ký tự trước có thể được khớp với 0 hoặc nhiều lần, thay vì chính xác một lần.

Ví dụ:

>>> import re
>>> p = re.compile('ab*')
>>> p
re.compile('ab*')
06 sẽ khớp với
>>> import re
>>> p = re.compile('ab*')
>>> p
re.compile('ab*')
07 (0
>>> m.group()
'tempo'
>>> m.start(), m.end()
(0, 5)
>>> m.span()
(0, 5)
2 ký tự),
>>> import re
>>> p = re.compile('ab*')
>>> p
re.compile('ab*')
09 (1
>>> m.group()
'tempo'
>>> m.start(), m.end()
(0, 5)
>>> m.span()
(0, 5)
2),
>>> import re
>>> p = re.compile('ab*')
>>> p
re.compile('ab*')
11 (3
>>> m.group()
'tempo'
>>> m.start(), m.end()
(0, 5)
>>> m.span()
(0, 5)
2 ký tự), v.v.

Sự lặp lại như

>>> import re
>>> p = re.compile('ab*')
>>> p
re.compile('ab*')
03 là tham lam; Khi lặp lại một RE, động cơ phù hợp sẽ cố gắng lặp lại nó càng nhiều lần càng tốt. Nếu các phần sau của mẫu don don phù hợp, động cơ phù hợp sau đó sẽ sao lưu và thử lại với ít sự lặp lại hơn.

Một ví dụ từng bước sẽ làm cho điều này rõ ràng hơn. Hãy cùng xem xét biểu thức

>>> import re
>>> p = re.compile('ab*')
>>> p
re.compile('ab*')
14. Điều này phù hợp với chữ cái
>>> m.group()
'tempo'
>>> m.start(), m.end()
(0, 5)
>>> m.span()
(0, 5)
2, không hoặc nhiều chữ cái từ lớp
>>> import re
>>> p = re.compile('ab*')
>>> p
re.compile('ab*')
16 và cuối cùng kết thúc bằng
>>> import re
>>> p = re.compile('ab*')
>>> p
re.compile('ab*')
17. Bây giờ hãy tưởng tượng phù hợp với RE này với chuỗi
>>> import re
>>> p = re.compile('ab*')
>>> p
re.compile('ab*')
18.

Bươc

Phù hợp

Giải trình

1

>>> m = p.match('tempo')
>>> m

5

>>> m = p.match('tempo')
>>> m

5 trong các trận đấu RE.

2

>>> import re
>>> p = re.compile('ab*')
>>> p
re.compile('ab*')
21

Động cơ phù hợp với

>>> import re
>>> p = re.compile('ab*')
>>> p
re.compile('ab*')
22, đi xa nhất có thể, đến cuối chuỗi.

3

Thất bại

Động cơ cố gắng phù hợp với

>>> m = p.match('tempo')
>>> m

6, nhưng vị trí hiện tại ở cuối chuỗi, vì vậy nó không thành công.

4

>>> import re
>>> p = re.compile('ab*')
>>> p
re.compile('ab*')
24

Sao lưu, để

>>> import re
>>> p = re.compile('ab*')
>>> p
re.compile('ab*')
22 khớp với một ký tự ít hơn.

5

Thất bại

Động cơ cố gắng phù hợp với

>>> m = p.match('tempo')
>>> m

6, nhưng vị trí hiện tại ở cuối chuỗi, vì vậy nó không thành công.

6

>>> import re
>>> p = re.compile('ab*')
>>> p
re.compile('ab*')
28

Sao lưu, để

>>> import re
>>> p = re.compile('ab*')
>>> p
re.compile('ab*')
22 khớp với một ký tự ít hơn.

6

>>> import re
>>> p = re.compile('ab*')
>>> p
re.compile('ab*')
24

Hãy thử một lần nữa, nhưng vị trí hiện tại là ở ký tự cuối cùng, đó là một

>>> import re
>>> p = re.compile('ab*')
>>> p
re.compile('ab*')
27.

Sao lưu lại, để

>>> import re
>>> p = re.compile('ab*')
>>> p
re.compile('ab*')
22 chỉ khớp với
>>> import re
>>> p = re.compile('ab*')
>>> p
re.compile('ab*')
30.

Hãy thử lại

>>> m = p.match('tempo')
>>> m

6. Lần này, nhân vật ở vị trí hiện tại là
>>> import re
>>> p = re.compile('ab*')
>>> p
re.compile('ab*')
17, vì vậy nó thành công.

Có hai toán tử hoặc định lượng lặp lại. Ký tự dấu câu hỏi,

>>> import re
>>> p = re.compile('ab*')
>>> p
re.compile('ab*')
47, khớp với một lần hoặc bằng không; Bạn có thể nghĩ về nó là đánh dấu một cái gì đó là tùy chọn. Ví dụ:
>>> import re
>>> p = re.compile('ab*')
>>> p
re.compile('ab*')
48 khớp với
>>> import re
>>> p = re.compile('ab*')
>>> p
re.compile('ab*')
49 hoặc
>>> import re
>>> p = re.compile('ab*')
>>> p
re.compile('ab*')
50.

Bộ định lượng phức tạp nhất là

>>> import re
>>> p = re.compile('ab*')
>>> p
re.compile('ab*')
51, trong đó m và n là số nguyên thập phân. Định lượng này có nghĩa là phải có ít nhất m lần lặp lại, và nhiều nhất là n. Ví dụ,
>>> import re
>>> p = re.compile('ab*')
>>> p
re.compile('ab*')
52 sẽ khớp với
>>> import re
>>> p = re.compile('ab*')
>>> p
re.compile('ab*')
53,
>>> import re
>>> p = re.compile('ab*')
>>> p
re.compile('ab*')
54 và
>>> import re
>>> p = re.compile('ab*')
>>> p
re.compile('ab*')
55. Nó đã thắng trận đấu
>>> import re
>>> p = re.compile('ab*')
>>> p
re.compile('ab*')
56, không có dấu gạch chéo, hoặc
>>> import re
>>> p = re.compile('ab*')
>>> p
re.compile('ab*')
57, có bốn.

Bạn có thể bỏ qua m hoặc n; Trong trường hợp đó, một giá trị hợp lý được giả định cho giá trị bị thiếu. Bỏ qua M được hiểu là giới hạn thấp hơn 0, trong khi bỏ qua N dẫn đến giới hạn trên của vô cực.

Độc giả của một người bị giảm bớt có thể nhận thấy rằng ba định lượng khác đều có thể được thể hiện bằng cách sử dụng ký hiệu này.

>>> import re
>>> p = re.compile('ab*')
>>> p
re.compile('ab*')
58 giống như
>>> import re
>>> p = re.compile('ab*')
>>> p
re.compile('ab*')
03,
>>> import re
>>> p = re.compile('ab*')
>>> p
re.compile('ab*')
60 tương đương với
>>> import re
>>> p = re.compile('ab*')
>>> p
re.compile('ab*')
36 và
>>> import re
>>> p = re.compile('ab*')
>>> p
re.compile('ab*')
62 giống như
>>> import re
>>> p = re.compile('ab*')
>>> p
re.compile('ab*')
47. Nó tốt hơn để sử dụng
>>> import re
>>> p = re.compile('ab*')
>>> p
re.compile('ab*')
03,
>>> import re
>>> p = re.compile('ab*')
>>> p
re.compile('ab*')
36 hoặc
>>> import re
>>> p = re.compile('ab*')
>>> p
re.compile('ab*')
47 khi bạn có thể, chỉ vì chúng ngắn hơn và dễ đọc hơn.

Sử dụng các biểu thức thông thường

Bây giờ chúng tôi đã xem xét một số biểu thức thông thường đơn giản, làm thế nào để chúng ta thực sự sử dụng chúng trong Python? Mô -đun

>>> p.match("")
>>> print(p.match(""))
None
5 cung cấp một giao diện cho công cụ biểu thức chính quy, cho phép bạn biên dịch RES vào các đối tượng và sau đó thực hiện các trận đấu với chúng.

Biên soạn các biểu thức chính quy

Các biểu thức chính quy được biên dịch thành các đối tượng mẫu, có các phương thức cho các hoạt động khác nhau như tìm kiếm các kết quả phù hợp mẫu hoặc thực hiện thay thế chuỗi.

>>> import re
>>> p = re.compile('ab*')
>>> p
re.compile('ab*')

>>> import re
>>> p = re.compile('ab*')
>>> p
re.compile('ab*')
68 cũng chấp nhận một đối số cờ tùy chọn, được sử dụng để kích hoạt các tính năng đặc biệt và biến thể cú pháp khác nhau. Chúng tôi sẽ đi qua các cài đặt có sẵn sau, nhưng bây giờ một ví dụ sẽ làm:

>>> p = re.compile('ab*', re.IGNORECASE)

RE được truyền đến

>>> import re
>>> p = re.compile('ab*')
>>> p
re.compile('ab*')
68 dưới dạng chuỗi. RES được xử lý như các chuỗi vì các biểu thức thông thường không phải là một phần của ngôn ngữ Python cốt lõi và không có cú pháp đặc biệt nào được tạo ra để thể hiện chúng. .

Đặt res vào các chuỗi giữ cho ngôn ngữ Python đơn giản hơn, nhưng có một nhược điểm đó là chủ đề của phần tiếp theo.

Bệnh dịch hạch ngược

Như đã nêu trước đó, các biểu thức chính quy sử dụng ký tự dấu gạch chéo ngược (

>>> print(p.match('::: message'))
None
>>> m = p.search('::: message'); print(m)

>>> m.group()
'message'
>>> m.span()
(4, 11)
8) để biểu thị các hình thức đặc biệt hoặc cho phép các ký tự đặc biệt được sử dụng mà không cần gọi ý nghĩa đặc biệt của chúng. Điều này mâu thuẫn với việc sử dụng Python sườn của cùng một nhân vật cho cùng một mục đích trong các chữ viết.

Hãy nói rằng bạn muốn viết một RE phù hợp với chuỗi

>>> import re
>>> p = re.compile('ab*')
>>> p
re.compile('ab*')
74, có thể được tìm thấy trong một tệp latex. Để tìm ra những gì cần viết trong mã chương trình, hãy bắt đầu với chuỗi mong muốn được khớp. Tiếp theo, bạn phải thoát khỏi bất kỳ dấu gạch chéo ngược nào và các metacharacters khác bằng cách trước chúng bằng một dấu gạch chéo ngược, dẫn đến chuỗi
>>> import re
>>> p = re.compile('ab*')
>>> p
re.compile('ab*')
75. Chuỗi kết quả phải được truyền đến
>>> import re
>>> p = re.compile('ab*')
>>> p
re.compile('ab*')
68 phải là
>>> import re
>>> p = re.compile('ab*')
>>> p
re.compile('ab*')
75. Tuy nhiên, để thể hiện điều này như một chuỗi Python theo nghĩa đen, cả hai dấu gạch chéo ngược phải được thoát ra một lần nữa.

Nhân vật

Sân khấu

>>> import re
>>> p = re.compile('ab*')
>>> p
re.compile('ab*')
74

Chuỗi văn bản được khớp

>>> import re
>>> p = re.compile('ab*')
>>> p
re.compile('ab*')
75

Đã thoát khỏi sự chéo ngược cho

>>> import re
>>> p = re.compile('ab*')
>>> p
re.compile('ab*')
68

>>> import re
>>> p = re.compile('ab*')
>>> p
re.compile('ab*')
81

Thoát khỏi sự chéo ngược cho một chuỗi theo nghĩa đen

Nói tóm lại, để phù hợp với một dấu gạch chéo ngược theo nghĩa đen, người ta phải viết

>>> import re
>>> p = re.compile('ab*')
>>> p
re.compile('ab*')
82 dưới dạng chuỗi RE, bởi vì biểu thức thông thường phải là
>>> print(p.match('::: message'))
None
>>> m = p.search('::: message'); print(m)

>>> m.group()
'message'
>>> m.span()
(4, 11)
7 và mỗi dấu gạch chéo ngược phải được biểu thị dưới dạng
>>> print(p.match('::: message'))
None
>>> m = p.search('::: message'); print(m)

>>> m.group()
'message'
>>> m.span()
(4, 11)
7 bên trong một chuỗi python thông thường theo nghĩa đen. Trong RES đó là các dấu gạch chéo ngược nhiều lần, điều này dẫn đến rất nhiều dấu gạch chéo ngược lặp đi lặp lại và làm cho các chuỗi kết quả khó hiểu.

Giải pháp là sử dụng ký hiệu chuỗi thô Python sườn cho các biểu thức thông thường; Backslashes không được xử lý theo bất kỳ cách đặc biệt nào trong một chuỗi theo nghĩa đen được đặt trước với

>>> import re
>>> p = re.compile('ab*')
>>> p
re.compile('ab*')
85, vì vậy
>>> import re
>>> p = re.compile('ab*')
>>> p
re.compile('ab*')
86 là một chuỗi hai ký tự có chứa
>>> print(p.match('::: message'))
None
>>> m = p.search('::: message'); print(m)

>>> m.group()
'message'
>>> m.span()
(4, 11)
8 và
>>> import re
>>> p = re.compile('ab*')
>>> p
re.compile('ab*')
88, trong khi
>>> import re
>>> p = re.compile('ab*')
>>> p
re.compile('ab*')
89 là chuỗi một ký tự có chứa một dòng mới. Biểu thức chính quy thường sẽ được viết bằng mã Python bằng cách sử dụng ký hiệu chuỗi thô này.

Ngoài ra, các chuỗi thoát đặc biệt có giá trị trong các biểu thức chính quy, nhưng không hợp lệ như các chữ Python, bây giờ dẫn đến

>>> import re
>>> p = re.compile('ab*')
>>> p
re.compile('ab*')
90 và cuối cùng sẽ trở thành
>>> import re
>>> p = re.compile('ab*')
>>> p
re.compile('ab*')
91, có nghĩa là các chuỗi sẽ không hợp lệ nếu ký hiệu chuỗi thô hoặc thoát khỏi các dấu gạch chéo ngược không phải là ' t sử dụng.

Chuỗi thông thường

Chuỗi thô

>>> import re
>>> p = re.compile('ab*')
>>> p
re.compile('ab*')
92

>>> import re
>>> p = re.compile('ab*')
>>> p
re.compile('ab*')
93

>>> import re
>>> p = re.compile('ab*')
>>> p
re.compile('ab*')
81

>>> import re
>>> p = re.compile('ab*')
>>> p
re.compile('ab*')
95

>>> import re
>>> p = re.compile('ab*')
>>> p
re.compile('ab*')
96

>>> import re
>>> p = re.compile('ab*')
>>> p
re.compile('ab*')
97

Thực hiện các trận đấu

Khi bạn có một đối tượng đại diện cho một biểu thức thông thường được biên dịch, bạn sẽ làm gì với nó? Đối tượng mẫu có một số phương thức và thuộc tính. Chỉ những người quan trọng nhất sẽ được đề cập ở đây; Tham khảo các tài liệu

>>> p.match("")
>>> print(p.match(""))
None
5 để biết danh sách đầy đủ.

Method/Attribute

Mục đích

>>> import re
>>> p = re.compile('ab*')
>>> p
re.compile('ab*')
99

Xác định xem RE có khớp ở đầu chuỗi không.

>>> p = re.compile('ab*', re.IGNORECASE)
00

Quét qua một chuỗi, tìm kiếm bất kỳ vị trí nào mà điều này phù hợp.

>>> p = re.compile('ab*', re.IGNORECASE)
01

Tìm tất cả các chuỗi con nơi RE khớp với nhau và trả về chúng dưới dạng danh sách.

>>> p = re.compile('ab*', re.IGNORECASE)
02

Tìm tất cả các chuỗi con nơi RE khớp với nhau và trả về chúng như một trình lặp lại.iterator.

>>> import re
>>> p = re.compile('ab*')
>>> p
re.compile('ab*')
99 và
>>> p = re.compile('ab*', re.IGNORECASE)
00 Trả về
>>> p = re.compile('ab*', re.IGNORECASE)
05 nếu không thể tìm thấy trận đấu. Nếu họ thành công, một thể hiện đối tượng phù hợp được trả về, chứa thông tin về trận đấu: nơi nó bắt đầu và kết thúc, phần phụ mà nó khớp và hơn thế nữa.match object instance is returned, containing information about the match: where it starts and ends, the substring it matched, and more.

Bạn có thể tìm hiểu về điều này bằng cách thử nghiệm tương tác với mô -đun

>>> p.match("")
>>> print(p.match(""))
None
5. Nếu bạn có sẵn
>>> p = re.compile('ab*', re.IGNORECASE)
07, bạn cũng có thể muốn xem các công cụ/demo/redemo.py, một chương trình trình diễn có trong phân phối Python. Nó cho phép bạn nhập RES và chuỗi, và hiển thị cho dù RE khớp hay thất bại.
>>> p = re.compile('ab*', re.IGNORECASE)
08 có thể khá hữu ích khi cố gắng gỡ lỗi RE phức tạp.

Howto này sử dụng trình thông dịch Python tiêu chuẩn cho các ví dụ của nó. Đầu tiên, chạy trình thông dịch Python, nhập mô -đun

>>> p.match("")
>>> print(p.match(""))
None
5 và biên dịch một Re:

>>> import re
>>> p = re.compile('[a-z]+')
>>> p
re.compile('[a-z]+')

Bây giờ, bạn có thể thử khớp các chuỗi khác nhau với RE

>>> p = re.compile('ab*', re.IGNORECASE)
10. Một chuỗi trống không nên khớp với nhau, vì
>>> import re
>>> p = re.compile('ab*')
>>> p
re.compile('ab*')
36 có nghĩa là ‘một hoặc nhiều lần lặp lại.
>>> import re
>>> p = re.compile('ab*')
>>> p
re.compile('ab*')
99 sẽ trả về
>>> p = re.compile('ab*', re.IGNORECASE)
05 trong trường hợp này, điều này sẽ khiến thông dịch viên không in đầu ra. Bạn có thể in rõ ràng kết quả của
>>> import re
>>> p = re.compile('ab*')
>>> p
re.compile('ab*')
99 để làm rõ điều này.

>>> p.match("")
>>> print(p.match(""))
None

Bây giờ, hãy để thử nó trên một chuỗi mà nó sẽ phù hợp, chẳng hạn như

>>> p = re.compile('ab*', re.IGNORECASE)
15. Trong trường hợp này,
>>> import re
>>> p = re.compile('ab*')
>>> p
re.compile('ab*')
99 sẽ trả về một đối tượng khớp, vì vậy bạn nên lưu trữ kết quả trong một biến để sử dụng sau.match object, so you should store the result in a variable for later use.

>>> m = p.match('tempo')
>>> m

Bây giờ bạn có thể truy vấn đối tượng khớp để biết thông tin về chuỗi khớp. Các trường hợp đối tượng khớp cũng có một số phương thức và thuộc tính; Những cái quan trọng nhất là:match object for information about the matching string. Match object instances also have several methods and attributes; the most important ones are:

Method/Attribute

Mục đích

>>> p = re.compile('ab*', re.IGNORECASE)
17

Xác định xem RE có khớp ở đầu chuỗi không.

>>> p = re.compile('ab*', re.IGNORECASE)
18

Quét qua một chuỗi, tìm kiếm bất kỳ vị trí nào mà điều này phù hợp.

>>> p = re.compile('ab*', re.IGNORECASE)
19

Tìm tất cả các chuỗi con nơi RE khớp với nhau và trả về chúng dưới dạng danh sách.

>>> p = re.compile('ab*', re.IGNORECASE)
20

Tìm tất cả các chuỗi con nơi RE khớp với nhau và trả về chúng như một trình lặp lại.

>>> import re
>>> p = re.compile('ab*')
>>> p
re.compile('ab*')
99 và
>>> p = re.compile('ab*', re.IGNORECASE)
00 Trả về
>>> p = re.compile('ab*', re.IGNORECASE)
05 nếu không thể tìm thấy trận đấu. Nếu họ thành công, một thể hiện đối tượng phù hợp được trả về, chứa thông tin về trận đấu: nơi nó bắt đầu và kết thúc, phần phụ mà nó khớp và hơn thế nữa.

>>> m.group()
'tempo'
>>> m.start(), m.end()
(0, 5)
>>> m.span()
(0, 5)

Bạn có thể tìm hiểu về điều này bằng cách thử nghiệm tương tác với mô -đun

>>> p.match("")
>>> print(p.match(""))
None
5. Nếu bạn có sẵn
>>> p = re.compile('ab*', re.IGNORECASE)
07, bạn cũng có thể muốn xem các công cụ/demo/redemo.py, một chương trình trình diễn có trong phân phối Python. Nó cho phép bạn nhập RES và chuỗi, và hiển thị cho dù RE khớp hay thất bại.
>>> p = re.compile('ab*', re.IGNORECASE)
08 có thể khá hữu ích khi cố gắng gỡ lỗi RE phức tạp.

>>> print(p.match('::: message'))
None
>>> m = p.search('::: message'); print(m)

>>> m.group()
'message'
>>> m.span()
(4, 11)

Howto này sử dụng trình thông dịch Python tiêu chuẩn cho các ví dụ của nó. Đầu tiên, chạy trình thông dịch Python, nhập mô -đun

>>> p.match("")
>>> print(p.match(""))
None
5 và biên dịch một Re:match object in a variable, and then check if it was
>>> p = re.compile('ab*', re.IGNORECASE)
05. This usually looks like:

p = re.compile( ... )
m = p.match( 'string goes here' )
if m:
    print('Match found: ', m.group())
else:
    print('No match')

Bây giờ, bạn có thể thử khớp các chuỗi khác nhau với RE

>>> p = re.compile('ab*', re.IGNORECASE)
10. Một chuỗi trống không nên khớp với nhau, vì
>>> import re
>>> p = re.compile('ab*')
>>> p
re.compile('ab*')
36 có nghĩa là ‘một hoặc nhiều lần lặp lại.
>>> import re
>>> p = re.compile('ab*')
>>> p
re.compile('ab*')
99 sẽ trả về
>>> p = re.compile('ab*', re.IGNORECASE)
05 trong trường hợp này, điều này sẽ khiến thông dịch viên không in đầu ra. Bạn có thể in rõ ràng kết quả của
>>> import re
>>> p = re.compile('ab*')
>>> p
re.compile('ab*')
99 để làm rõ điều này.

>>> p = re.compile(r'\d+')
>>> p.findall('12 drummers drumming, 11 pipers piping, 10 lords a-leaping')
['12', '11', '10']

Bây giờ, hãy để thử nó trên một chuỗi mà nó sẽ phù hợp, chẳng hạn như

>>> p = re.compile('ab*', re.IGNORECASE)
15. Trong trường hợp này,
>>> import re
>>> p = re.compile('ab*')
>>> p
re.compile('ab*')
99 sẽ trả về một đối tượng khớp, vì vậy bạn nên lưu trữ kết quả trong một biến để sử dụng sau.The Backslash Plague.

Bây giờ bạn có thể truy vấn đối tượng khớp để biết thông tin về chuỗi khớp. Các trường hợp đối tượng khớp cũng có một số phương thức và thuộc tính; Những cái quan trọng nhất là:match object instances as an iterator:

>>> import re
>>> p = re.compile('ab*')
>>> p
re.compile('ab*')
0

Trả về chuỗi phù hợp với re

Trả về vị trí bắt đầu của trận đấumatch object instance.

>>> import re
>>> p = re.compile('ab*')
>>> p
re.compile('ab*')
1

Trả về vị trí kết thúc của trận đấu

Trả về một tuple chứa các vị trí (bắt đầu, kết thúc) của trận đấu

Cờ tổng hợp

Cờ biên dịch cho phép bạn sửa đổi một số khía cạnh về cách thức biểu thức thường xuyên hoạt động. Cờ có sẵn trong mô-đun

>>> p.match("")
>>> print(p.match(""))
None
5 dưới hai tên, một tên dài như
>>> p = re.compile('ab*', re.IGNORECASE)
42 và một hình thức ngắn, một chữ cái như
>>> p = re.compile('ab*', re.IGNORECASE)
43. . Ví dụ,
>>> p = re.compile('ab*', re.IGNORECASE)
46 đặt cả hai cờ
>>> p = re.compile('ab*', re.IGNORECASE)
43 và
>>> p = re.compile('ab*', re.IGNORECASE)
48.

Ở đây, một bảng của các cờ có sẵn, tiếp theo là một lời giải thích chi tiết hơn về từng người.

Lá cờ

Nghĩa

>>> p = re.compile('ab*', re.IGNORECASE)
49,
>>> p = re.compile('ab*', re.IGNORECASE)
50

Làm cho một số lối thoát như

>>> print(p.match('::: message'))
None
>>> m = p.search('::: message'); print(m)

>>> m.group()
'message'
>>> m.span()
(4, 11)
9,
>>> p = re.compile('ab*', re.IGNORECASE)
52,
p = re.compile( ... )
m = p.match( 'string goes here' )
if m:
    print('Match found: ', m.group())
else:
    print('No match')
9 và
p = re.compile( ... )
m = p.match( 'string goes here' )
if m:
    print('Match found: ', m.group())
else:
    print('No match')
5 chỉ khớp với các ký tự ASCII với thuộc tính tương ứng.

>>> p = re.compile('ab*', re.IGNORECASE)
55,
>>> p = re.compile('ab*', re.IGNORECASE)
56

Tạo

>>> import re
>>> p = re.compile('ab*')
>>> p
re.compile('ab*')
00 khớp với bất kỳ nhân vật nào, bao gồm cả dòng mới.

>>> p = re.compile('ab*', re.IGNORECASE)
42,
>>> p = re.compile('ab*', re.IGNORECASE)
43

Làm các trận đấu không nhạy cảm trường hợp.

>>> p = re.compile('ab*', re.IGNORECASE)
60,
>>> p = re.compile('ab*', re.IGNORECASE)
61

Làm một trận đấu nhận biết địa phương.

>>> p = re.compile('ab*', re.IGNORECASE)
62,
>>> p = re.compile('ab*', re.IGNORECASE)
48

Kết hợp đa dòng, ảnh hưởng đến

>>> p = re.compile('ab*', re.IGNORECASE)
64 và
>>> p = re.compile('ab*', re.IGNORECASE)
65.

>>> p = re.compile('ab*', re.IGNORECASE)
66,
>>> p = re.compile('ab*', re.IGNORECASE)
67 (cho ‘mở rộng)

Bật Res Verbose, có thể được tổ chức sạch sẽ và dễ hiểu hơn.

Iignorecase IGNORECASE

Thực hiện kết hợp không nhạy cảm trường hợp; lớp ký tự và chuỗi theo nghĩa đen sẽ phù hợp với các chữ cái bằng cách bỏ qua trường hợp. Ví dụ,

>>> p = re.compile('ab*', re.IGNORECASE)
68 cũng sẽ phù hợp với các chữ cái viết thường. Kết hợp toàn bộ Unicode cũng hoạt động trừ khi cờ
>>> p = re.compile('ab*', re.IGNORECASE)
49 được sử dụng để vô hiệu hóa các trận đấu không ASCII. Khi các mẫu Unicode
>>> m = p.match('tempo')
>>> m

9 hoặc
>>> p = re.compile('ab*', re.IGNORECASE)
68 được sử dụng kết hợp với cờ
>>> p = re.compile('ab*', re.IGNORECASE)
42, chúng sẽ khớp với 52 chữ cái ASCII và 4 chữ cái không ASCII bổ sung: ' '(U+0131, chữ nhỏ Latin không có dấu chấm i),' ſ '(u+017f, chữ nhỏ Latin dài s) và' k '(u+212a, dấu hiệu Kelvin).
>>> p = re.compile('ab*', re.IGNORECASE)
73 sẽ khớp với
>>> p = re.compile('ab*', re.IGNORECASE)
74,
>>> p = re.compile('ab*', re.IGNORECASE)
75,
>>> p = re.compile('ab*', re.IGNORECASE)
76 hoặc
>>> p = re.compile('ab*', re.IGNORECASE)
77 (cái sau chỉ phù hợp ở chế độ Unicode). Lowercasing này không tính đến địa phương hiện tại; Nó sẽ nếu bạn cũng đặt cờ
>>> p = re.compile('ab*', re.IGNORECASE)
60.

LLOCALE LOCALE

Tạo

>>> print(p.match('::: message'))
None
>>> m = p.search('::: message'); print(m)

>>> m.group()
'message'
>>> m.span()
(4, 11)
9,
>>> p = re.compile(r'\d+')
>>> p.findall('12 drummers drumming, 11 pipers piping, 10 lords a-leaping')
['12', '11', '10']
5,
>>> p = re.compile('ab*', re.IGNORECASE)
52,
>>> p = re.compile('ab*', re.IGNORECASE)
82 và khớp không nhạy cảm với trường hợp phụ thuộc vào ngôn ngữ hiện tại thay vì cơ sở dữ liệu Unicode.

Các địa phương là một tính năng của thư viện C nhằm giúp viết các chương trình có tính đến sự khác biệt ngôn ngữ. Ví dụ: nếu bạn xử lý văn bản Pháp được mã hóa, bạn sẽ muốn có thể viết

>>> p = re.compile('ab*', re.IGNORECASE)
83 để khớp các từ, nhưng
>>> print(p.match('::: message'))
None
>>> m = p.search('::: message'); print(m)

>>> m.group()
'message'
>>> m.span()
(4, 11)
9 chỉ khớp với lớp ký tự
>>> p = re.compile('ab*', re.IGNORECASE)
85 trong các mẫu byte; Nó đã giành chiến thắng trong các byte trận đấu tương ứng với
>>> p = re.compile('ab*', re.IGNORECASE)
86 hoặc
>>> p = re.compile('ab*', re.IGNORECASE)
87. Nếu hệ thống của bạn được cấu hình đúng cách và một địa phương Pháp được chọn, một số chức năng C nhất định sẽ nói với chương trình rằng byte tương ứng với
>>> p = re.compile('ab*', re.IGNORECASE)
86 cũng nên được coi là một lá thư. Đặt cờ
>>> p = re.compile('ab*', re.IGNORECASE)
60 khi biên dịch biểu thức chính quy sẽ khiến đối tượng được biên dịch kết quả sử dụng các hàm C này cho
>>> print(p.match('::: message'))
None
>>> m = p.search('::: message'); print(m)

>>> m.group()
'message'
>>> m.span()
(4, 11)
9; Điều này chậm hơn, nhưng cũng cho phép
>>> p = re.compile('ab*', re.IGNORECASE)
83 phù hợp với các từ tiếng Pháp như bạn mong đợi. Việc sử dụng lá cờ này không được khuyến khích trong Python 3 vì cơ chế địa phương rất không đáng tin cậy, nó chỉ xử lý một nền văn hóa của người Hồi giáo tại một thời điểm và nó chỉ hoạt động với các địa phương 8 bit. Kết hợp Unicode đã được bật theo mặc định trong Python 3 cho các mẫu Unicode (STR) và nó có thể xử lý các địa phương/ngôn ngữ khác nhau.

Mmultiline MULTILINE

.More Metacharacters.)

Thông thường

>>> p = re.compile('ab*', re.IGNORECASE)
64 chỉ khớp ở đầu chuỗi và
>>> p = re.compile('ab*', re.IGNORECASE)
65 chỉ khớp ở cuối chuỗi và ngay trước dòng mới (nếu có) ở cuối chuỗi. Khi cờ này được chỉ định,
>>> p = re.compile('ab*', re.IGNORECASE)
64 khớp ở đầu chuỗi và ở đầu mỗi dòng trong chuỗi, ngay lập tức theo từng dòng mới. Tương tự, metacharacter
>>> p = re.compile('ab*', re.IGNORECASE)
65 khớp với cuối chuỗi và ở cuối mỗi dòng (ngay trước mỗi dòng mới).

Sdotall DOTALL

Làm cho nhân vật đặc biệt

>>> p = re.compile(r'\d+')
>>> p.findall('12 drummers drumming, 11 pipers piping, 10 lords a-leaping')
['12', '11', '10']
9 khớp với bất kỳ nhân vật nào, bao gồm cả dòng mới; Không có cờ này,
>>> p = re.compile(r'\d+')
>>> p.findall('12 drummers drumming, 11 pipers piping, 10 lords a-leaping')
['12', '11', '10']
9 sẽ khớp với bất cứ điều gì ngoại trừ một dòng mới.

Aascii ASCII

Tạo

>>> print(p.match('::: message'))
None
>>> m = p.search('::: message'); print(m)

>>> m.group()
'message'
>>> m.span()
(4, 11)
9,
>>> p = re.compile(r'\d+')
>>> p.findall('12 drummers drumming, 11 pipers piping, 10 lords a-leaping')
['12', '11', '10']
5,
>>> p = re.compile('ab*', re.IGNORECASE)
52,
>>> p = re.compile('ab*', re.IGNORECASE)
82,
p = re.compile( ... )
m = p.match( 'string goes here' )
if m:
    print('Match found: ', m.group())
else:
    print('No match')
9 và
>>> p = re.compile(r'\d+')
>>> p.findall('12 drummers drumming, 11 pipers piping, 10 lords a-leaping')
['12', '11', '10']
1 thực hiện kết hợp ASCII-chỉ thay vì khớp unicode đầy đủ. Điều này chỉ có ý nghĩa đối với các mẫu Unicode và bị bỏ qua cho các mẫu byte.

Xverbose VERBOSE

Cờ này cho phép bạn viết các biểu thức thông thường dễ đọc hơn bằng cách cấp cho bạn sự linh hoạt hơn trong cách bạn có thể định dạng chúng. Khi lá cờ này đã được chỉ định, khoảng trắng trong chuỗi RE bị bỏ qua, ngoại trừ khi khoảng trắng nằm trong một lớp ký tự hoặc đi trước bởi một dấu gạch chéo ngược không được điều chỉnh; Điều này cho phép bạn tổ chức và thụt lề lại rõ ràng hơn. Cờ này cũng cho phép bạn đặt bình luận trong một RE sẽ bị động cơ bỏ qua; Nhận xét được đánh dấu bằng một

>>> import re
>>> p = re.compile('[a-z]+')
>>> p
re.compile('[a-z]+')
06 mà không có trong một lớp ký tự hoặc trước một dấu gạch chéo ngược không được phân loại.

Ví dụ, ở đây, một RE sử dụng

>>> p = re.compile('ab*', re.IGNORECASE)
44; Xem đọc dễ dàng hơn bao nhiêu?

>>> import re
>>> p = re.compile('ab*')
>>> p
re.compile('ab*')
2

Nếu không có cài đặt dài dòng, RE sẽ trông như thế này:

>>> import re
>>> p = re.compile('ab*')
>>> p
re.compile('ab*')
3

Trong ví dụ trên, sự kết nối tự động của các chuỗi chuỗi Python đã được sử dụng để chia RE thành các phần nhỏ hơn, nhưng nó vẫn khó hiểu hơn so với phiên bản sử dụng

>>> p = re.compile('ab*', re.IGNORECASE)
44.

Thêm Mẫu Power¶

Cho đến nay, chúng tôi chỉ bao gồm một phần các tính năng của các biểu thức thông thường. Trong phần này, chúng tôi sẽ bao gồm một số Metacharacters mới và cách sử dụng các nhóm để truy xuất các phần của văn bản được khớp.

Thêm Metacharacters¶

Có một số metacharacters mà chúng tôi đã bảo vệ. Hầu hết trong số họ sẽ được đề cập trong phần này.

Một số metacharacters còn lại sẽ được thảo luận là các xác nhận không có chiều rộng. Họ không làm cho động cơ tiến qua chuỗi; Thay vào đó, họ không tiêu thụ nhân vật nào cả, và chỉ đơn giản là thành công hay thất bại. Ví dụ,

>>> p = re.compile('ab*', re.IGNORECASE)
52 là một khẳng định rằng vị trí hiện tại được đặt tại một ranh giới từ; Vị trí này không được thay đổi bởi
>>> p = re.compile('ab*', re.IGNORECASE)
52. Điều này có nghĩa là các xác nhận không có chiều rộng không nên lặp lại, bởi vì nếu chúng khớp một lần tại một vị trí nhất định, rõ ràng chúng có thể được khớp với số lần vô hạn.

>>> import re
>>> p = re.compile('[a-z]+')
>>> p
re.compile('[a-z]+')
11

Sự xen kẽ, hoặc nhà điều hành của người khác. Nếu A và B là các biểu thức thông thường,

>>> import re
>>> p = re.compile('[a-z]+')
>>> p
re.compile('[a-z]+')
12 sẽ khớp với bất kỳ chuỗi nào khớp với A hoặc B.
>>> import re
>>> p = re.compile('[a-z]+')
>>> p
re.compile('[a-z]+')
11 có quyền ưu tiên rất thấp để làm cho nó hoạt động hợp lý khi bạn xen kẽ các chuỗi đa nhân.
>>> import re
>>> p = re.compile('[a-z]+')
>>> p
re.compile('[a-z]+')
14 sẽ khớp với
>>> import re
>>> p = re.compile('[a-z]+')
>>> p
re.compile('[a-z]+')
15 hoặc
>>> import re
>>> p = re.compile('[a-z]+')
>>> p
re.compile('[a-z]+')
16, không phải
>>> import re
>>> p = re.compile('[a-z]+')
>>> p
re.compile('[a-z]+')
17,
>>> import re
>>> p = re.compile('[a-z]+')
>>> p
re.compile('[a-z]+')
18 hoặc
>>> import re
>>> p = re.compile('[a-z]+')
>>> p
re.compile('[a-z]+')
19 và
>>> import re
>>> p = re.compile('[a-z]+')
>>> p
re.compile('[a-z]+')
20.

Để phù hợp với nghĩa đen

>>> import re
>>> p = re.compile('[a-z]+')
>>> p
re.compile('[a-z]+')
21, sử dụng
>>> import re
>>> p = re.compile('[a-z]+')
>>> p
re.compile('[a-z]+')
22 hoặc đặt nó bên trong một lớp ký tự, như trong
>>> import re
>>> p = re.compile('[a-z]+')
>>> p
re.compile('[a-z]+')
23.

>>> p = re.compile('ab*', re.IGNORECASE)
64

Phù hợp ở đầu dòng. Trừ khi cờ

>>> p = re.compile('ab*', re.IGNORECASE)
62 đã được đặt, điều này sẽ chỉ khớp ở đầu chuỗi. Trong chế độ
>>> p = re.compile('ab*', re.IGNORECASE)
62, điều này cũng khớp ngay sau mỗi dòng mới trong chuỗi.

Ví dụ: nếu bạn muốn khớp từ

>>> import re
>>> p = re.compile('[a-z]+')
>>> p
re.compile('[a-z]+')
27 chỉ ở đầu một dòng, hãy sử dụng lại là
>>> import re
>>> p = re.compile('[a-z]+')
>>> p
re.compile('[a-z]+')
28.

>>> import re
>>> p = re.compile('ab*')
>>> p
re.compile('ab*')
4

Để phù hợp với nghĩa đen

>>> m.group()
'tempo'
>>> m.start(), m.end()
(0, 5)
>>> m.span()
(0, 5)
7, sử dụng
>>> import re
>>> p = re.compile('[a-z]+')
>>> p
re.compile('[a-z]+')
30.

>>> p = re.compile('ab*', re.IGNORECASE)
65

Các khớp ở cuối dòng, được định nghĩa là đầu cuối của chuỗi hoặc bất kỳ vị trí nào theo sau là ký tự dòng mới.

>>> import re
>>> p = re.compile('ab*')
>>> p
re.compile('ab*')
5

Để phù hợp với nghĩa đen

>>> m.group()
'tempo'
>>> m.start(), m.end()
(0, 5)
>>> m.span()
(0, 5)
5, sử dụng
>>> import re
>>> p = re.compile('[a-z]+')
>>> p
re.compile('[a-z]+')
33 hoặc đặt nó bên trong một lớp ký tự, như trong
>>> import re
>>> p = re.compile('[a-z]+')
>>> p
re.compile('[a-z]+')
34.

>>> import re
>>> p = re.compile('[a-z]+')
>>> p
re.compile('[a-z]+')
35

Chỉ khớp khi bắt đầu chuỗi. Khi không ở chế độ

>>> p = re.compile('ab*', re.IGNORECASE)
62,
>>> import re
>>> p = re.compile('[a-z]+')
>>> p
re.compile('[a-z]+')
35 và
>>> p = re.compile('ab*', re.IGNORECASE)
64 có hiệu quả giống nhau. Trong chế độ
>>> p = re.compile('ab*', re.IGNORECASE)
62, chúng khác nhau:
>>> import re
>>> p = re.compile('[a-z]+')
>>> p
re.compile('[a-z]+')
35 vẫn chỉ khớp với đầu chuỗi, nhưng
>>> p = re.compile('ab*', re.IGNORECASE)
64 có thể khớp tại bất kỳ vị trí nào bên trong chuỗi theo ký tự mới.

>>> import re
>>> p = re.compile('[a-z]+')
>>> p
re.compile('[a-z]+')
42

Chỉ khớp ở cuối chuỗi.

>>> p = re.compile('ab*', re.IGNORECASE)
52

Ranh giới từ. Đây là một khẳng định không có chiều rộng không chỉ khớp với đầu hoặc cuối của một từ. Một từ được định nghĩa là một chuỗi các ký tự chữ và số, do đó, phần cuối của một từ được biểu thị bằng khoảng trắng hoặc một ký tự không phải là vô sinh.

Ví dụ sau đây chỉ khớp với

>>> import re
>>> p = re.compile('[a-z]+')
>>> p
re.compile('[a-z]+')
44 khi nó có một từ hoàn chỉnh; Nó đã thắng trận đấu khi nó chứa trong một từ khác.

>>> import re
>>> p = re.compile('ab*')
>>> p
re.compile('ab*')
6

Có hai sự tinh tế bạn nên nhớ khi sử dụng chuỗi đặc biệt này. Đầu tiên, đây là sự va chạm tồi tệ nhất giữa các chuỗi chữ Python và trình tự biểu thức chính quy. Trong các chuỗi chữ Python,

>>> p = re.compile('ab*', re.IGNORECASE)
52 là ký tự backspace, giá trị ASCII 8. Nếu bạn không sử dụng các chuỗi thô, thì Python sẽ chuyển đổi
>>> p = re.compile('ab*', re.IGNORECASE)
52 thành một backspace và bạn đã giành chiến thắng khi bạn mong đợi. Ví dụ sau đây trông giống như RE trước đây của chúng tôi, nhưng bỏ qua
>>> import re
>>> p = re.compile('ab*')
>>> p
re.compile('ab*')
85 phía trước chuỗi RE.

>>> import re
>>> p = re.compile('ab*')
>>> p
re.compile('ab*')
7

Thứ hai, bên trong một lớp ký tự, trong đó không có cách sử dụng cho khẳng định này,

>>> p = re.compile('ab*', re.IGNORECASE)
52 đại diện cho ký tự backspace, để tương thích với các chữ Python tựa.

>>> p = re.compile('ab*', re.IGNORECASE)
82

Một khẳng định không có chiều rộng khác, điều này đối nghịch với

>>> p = re.compile('ab*', re.IGNORECASE)
52, chỉ khớp khi vị trí hiện tại không ở ranh giới từ.

Nhóm

Thường thì bạn cần có thêm thông tin hơn là liệu RE có khớp hay không. Các biểu thức chính quy thường được sử dụng để mổ xẻ các chuỗi bằng cách viết một RE được chia thành một số nhóm nhỏ phù hợp với các thành phần quan tâm khác nhau. Ví dụ, đường tiêu đề RFC-822 được chia thành tên tiêu đề và giá trị, được phân tách bằng

>>> import re
>>> p = re.compile('[a-z]+')
>>> p
re.compile('[a-z]+')
51, như thế này:

>>> import re
>>> p = re.compile('ab*')
>>> p
re.compile('ab*')
8

Điều này có thể được xử lý bằng cách viết một biểu thức thông thường phù hợp với toàn bộ dòng tiêu đề và có một nhóm phù hợp với tên tiêu đề và một nhóm khác phù hợp với giá trị tiêu đề.

Các nhóm được đánh dấu bởi

>>> import re
>>> p = re.compile('[a-z]+')
>>> p
re.compile('[a-z]+')
52,
>>> import re
>>> p = re.compile('[a-z]+')
>>> p
re.compile('[a-z]+')
53 Metacharacters.
>>> import re
>>> p = re.compile('[a-z]+')
>>> p
re.compile('[a-z]+')
52 và
>>> import re
>>> p = re.compile('[a-z]+')
>>> p
re.compile('[a-z]+')
53 có nhiều ý nghĩa giống như chúng làm trong các biểu thức toán học; Chúng nhóm lại các biểu thức chứa bên trong chúng và bạn có thể lặp lại nội dung của một nhóm có bộ định lượng, chẳng hạn như
>>> import re
>>> p = re.compile('ab*')
>>> p
re.compile('ab*')
03,
>>> import re
>>> p = re.compile('ab*')
>>> p
re.compile('ab*')
36,
>>> import re
>>> p = re.compile('ab*')
>>> p
re.compile('ab*')
47 hoặc
>>> import re
>>> p = re.compile('ab*')
>>> p
re.compile('ab*')
51. Ví dụ:
>>> import re
>>> p = re.compile('[a-z]+')
>>> p
re.compile('[a-z]+')
60 sẽ khớp với số không hoặc nhiều sự lặp lại của
>>> import re
>>> p = re.compile('[a-z]+')
>>> p
re.compile('[a-z]+')
61.

>>> import re
>>> p = re.compile('ab*')
>>> p
re.compile('ab*')
9

Các nhóm được chỉ định với

>>> import re
>>> p = re.compile('[a-z]+')
>>> p
re.compile('[a-z]+')
52,
>>> import re
>>> p = re.compile('[a-z]+')
>>> p
re.compile('[a-z]+')
53 cũng nắm bắt chỉ số bắt đầu và kết thúc của văn bản mà chúng phù hợp; Điều này có thể được lấy bằng cách chuyển một đối số cho
>>> p = re.compile('ab*', re.IGNORECASE)
17,
>>> p = re.compile('ab*', re.IGNORECASE)
18,
>>> p = re.compile('ab*', re.IGNORECASE)
19 và
>>> p = re.compile('ab*', re.IGNORECASE)
20. Các nhóm được đánh số bắt đầu với 0. Nhóm 0 luôn luôn có mặt; Nó có toàn bộ RE, vì vậy đều phù hợp với các phương thức đối tượng đều có nhóm 0 làm đối số mặc định của chúng. Sau đó, chúng tôi sẽ thấy cách thể hiện các nhóm không thể nắm bắt được khoảng của văn bản mà họ phù hợp.match object methods all have group 0 as their default argument. Later we’ll see how to express groups that don’t capture the span of text that they match.

>>> p = re.compile('ab*', re.IGNORECASE)
0

Các nhóm nhỏ được đánh số từ trái sang phải, từ 1 trở lên. Các nhóm có thể được lồng nhau; Để xác định số, chỉ cần đếm các ký tự dấu ngoặc đơn, đi từ trái sang phải.

>>> p = re.compile('ab*', re.IGNORECASE)
1

>>> p = re.compile('ab*', re.IGNORECASE)
17 có thể được truyền nhiều số nhóm tại một thời điểm, trong trường hợp đó, nó sẽ trả về một tuple chứa các giá trị tương ứng cho các nhóm đó.

>>> p = re.compile('ab*', re.IGNORECASE)
2

Phương pháp

>>> import re
>>> p = re.compile('[a-z]+')
>>> p
re.compile('[a-z]+')
69 trả về một tuple chứa các chuỗi cho tất cả các nhóm nhỏ, từ 1 trở lên tuy nhiên có nhiều thứ.

>>> p = re.compile('ab*', re.IGNORECASE)
3

Backrefer trong một mẫu cho phép bạn chỉ định rằng nội dung của một nhóm chụp trước đó cũng phải được tìm thấy tại vị trí hiện tại trong chuỗi. Ví dụ,

>>> import re
>>> p = re.compile('[a-z]+')
>>> p
re.compile('[a-z]+')
70 sẽ thành công nếu nội dung chính xác của nhóm 1 có thể được tìm thấy ở vị trí hiện tại và không thành công. Hãy nhớ rằng các chữ Python, theo nghĩa đen cũng sử dụng dấu gạch chéo ngược, theo sau là các số để cho phép bao gồm các ký tự tùy ý trong một chuỗi, vì vậy hãy chắc chắn sử dụng một chuỗi thô khi kết hợp các bản sao lưu trong một RE.

Ví dụ: RE sau đây phát hiện các từ nhân đôi trong một chuỗi.

>>> p = re.compile('ab*', re.IGNORECASE)
4

Các bản sao lưu như thế này, aren thường hữu ích khi chỉ tìm kiếm qua một chuỗi - có một vài định dạng văn bản lặp lại dữ liệu theo cách này - nhưng bạn sẽ sớm phát hiện ra rằng chúng rất hữu ích khi thực hiện thay thế chuỗi.

Các nhóm không bắt giữ và được đặt tên

Xây dựng RES có thể sử dụng nhiều nhóm, cả hai để nắm bắt các nền tảng quan tâm, và để nhóm và cấu trúc chính lại. Trong Res phức tạp, việc theo dõi các số nhóm trở nên khó khăn. Có hai tính năng giúp với vấn đề này. Cả hai đều sử dụng một cú pháp chung cho các phần mở rộng biểu thức thông thường, vì vậy chúng tôi sẽ xem xét điều đó trước.

Perl 5 nổi tiếng với các bổ sung mạnh mẽ cho các biểu thức chính quy tiêu chuẩn. Đối với các tính năng mới này, các nhà phát triển Perl không thể chọn các metacharacters phát âm đơn mới hoặc các chuỗi đặc biệt mới bắt đầu bằng

>>> m.group()
'tempo'
>>> m.start(), m.end()
(0, 5)
>>> m.span()
(0, 5)
0 mà không làm cho các biểu thức thường xuyên của Perl khác nhau một cách khó hiểu so với Res Standard. Ví dụ, nếu họ chọn
>>> import re
>>> p = re.compile('[a-z]+')
>>> p
re.compile('[a-z]+')
72 làm metacharacter mới, các biểu thức cũ sẽ cho rằng
>>> import re
>>> p = re.compile('[a-z]+')
>>> p
re.compile('[a-z]+')
72 là một nhân vật thường xuyên và sẽ thoát khỏi nó bằng cách viết
>>> import re
>>> p = re.compile('[a-z]+')
>>> p
re.compile('[a-z]+')
74 hoặc
>>> import re
>>> p = re.compile('[a-z]+')
>>> p
re.compile('[a-z]+')
75.

Giải pháp được các nhà phát triển Perl lựa chọn là sử dụng

>>> import re
>>> p = re.compile('[a-z]+')
>>> p
re.compile('[a-z]+')
76 làm cú pháp mở rộng.
>>> import re
>>> p = re.compile('ab*')
>>> p
re.compile('ab*')
47 ngay sau khi dấu ngoặc đơn là lỗi cú pháp vì
>>> import re
>>> p = re.compile('ab*')
>>> p
re.compile('ab*')
47 sẽ không có gì để lặp lại, vì vậy điều này đã không đưa ra bất kỳ vấn đề tương thích nào. Các ký tự ngay sau khi
>>> import re
>>> p = re.compile('ab*')
>>> p
re.compile('ab*')
47 cho biết phần mở rộng nào đang được sử dụng, vì vậy
>>> import re
>>> p = re.compile('[a-z]+')
>>> p
re.compile('[a-z]+')
80 là một điều (khẳng định xem xét tích cực) và
>>> import re
>>> p = re.compile('[a-z]+')
>>> p
re.compile('[a-z]+')
81 là một cái gì đó khác (một nhóm không bắt giữ chứa biểu thức phụ
>>> import re
>>> p = re.compile('[a-z]+')
>>> p
re.compile('[a-z]+')
82).

Python hỗ trợ một số tiện ích mở rộng Perl Perl và thêm cú pháp mở rộng vào cú pháp mở rộng Perl. Nếu nhân vật đầu tiên sau dấu hỏi là

>>> import re
>>> p = re.compile('[a-z]+')
>>> p
re.compile('[a-z]+')
83, bạn sẽ biết rằng nó là một phần mở rộng mà đặc trưng cho Python.

Bây giờ chúng tôi đã xem xét cú pháp mở rộng chung, chúng tôi có thể quay lại các tính năng đơn giản hóa việc làm việc với các nhóm trong Res phức tạp.

Đôi khi, bạn sẽ muốn sử dụng một nhóm để biểu thị một phần của biểu thức thông thường, nhưng aren quan tâm đến việc truy xuất nội dung của nhóm. Bạn có thể làm rõ thực tế này bằng cách sử dụng một nhóm không bắt giữ:

>>> import re
>>> p = re.compile('[a-z]+')
>>> p
re.compile('[a-z]+')
84, trong đó bạn có thể thay thế
>>> import re
>>> p = re.compile('[a-z]+')
>>> p
re.compile('[a-z]+')
85 bằng bất kỳ biểu thức thông thường nào khác.

>>> p = re.compile('ab*', re.IGNORECASE)
5

Ngoại trừ thực tế là bạn có thể lấy lại nội dung của những gì nhóm phù hợp, một nhóm không bắt giữ hoạt động giống hệt như một nhóm bắt giữ; Bạn có thể đặt bất cứ thứ gì bên trong nó, lặp lại nó với một metacharacter lặp lại như

>>> import re
>>> p = re.compile('ab*')
>>> p
re.compile('ab*')
03 và làm tổ nó trong các nhóm khác (bắt hoặc không bắt).
>>> import re
>>> p = re.compile('[a-z]+')
>>> p
re.compile('[a-z]+')
84 đặc biệt hữu ích khi sửa đổi một mẫu hiện có, vì bạn có thể thêm các nhóm mới mà không thay đổi cách tất cả các nhóm khác được đánh số. Cần phải đề cập rằng không có sự khác biệt về hiệu suất trong việc tìm kiếm giữa các nhóm bắt giữ và không bắt giữ; Không hình thức nào nhanh hơn hình thức khác.

Một tính năng quan trọng hơn được đặt tên là các nhóm: thay vì đề cập đến chúng theo số, các nhóm có thể được tham chiếu bằng một tên.

Cú pháp cho một nhóm được đặt tên là một trong những tiện ích mở rộng cụ thể của Python:

>>> import re
>>> p = re.compile('[a-z]+')
>>> p
re.compile('[a-z]+')
88. Tên là, rõ ràng, tên của nhóm. Các nhóm được đặt tên hoạt động chính xác giống như bắt giữ các nhóm, và cũng liên kết một tên với một nhóm. Các phương thức đối tượng khớp liên quan đến việc thu thập các nhóm đều chấp nhận các số nguyên đề cập đến nhóm theo số hoặc các chuỗi có chứa tên nhóm mong muốn. Các nhóm được đặt tên vẫn được đưa ra các số, vì vậy bạn có thể truy xuất thông tin về một nhóm theo hai cách:match object methods that deal with capturing groups all accept either integers that refer to the group by number or strings that contain the desired group’s name. Named groups are still given numbers, so you can retrieve information about a group in two ways:

>>> p = re.compile('ab*', re.IGNORECASE)
6

Ngoài ra, bạn có thể truy xuất các nhóm được đặt tên là từ điển với

>>> import re
>>> p = re.compile('[a-z]+')
>>> p
re.compile('[a-z]+')
89:

>>> p = re.compile('ab*', re.IGNORECASE)
7

Các nhóm được đặt tên là tiện dụng vì họ cho phép bạn sử dụng tên dễ nhớ, thay vì phải nhớ số. Ở đây, một ví dụ RE từ mô -đun

>>> import re
>>> p = re.compile('[a-z]+')
>>> p
re.compile('[a-z]+')
90:

>>> p = re.compile('ab*', re.IGNORECASE)
8

Nó rõ ràng dễ dàng hơn nhiều để lấy

>>> import re
>>> p = re.compile('[a-z]+')
>>> p
re.compile('[a-z]+')
91, thay vì phải nhớ lấy lại nhóm 9.

Cú pháp cho các bản sao lưu trong một biểu thức như

>>> import re
>>> p = re.compile('[a-z]+')
>>> p
re.compile('[a-z]+')
92 đề cập đến số lượng của nhóm. Có một cách tự nhiên một biến thể sử dụng tên nhóm thay vì số. Đây là một phần mở rộng Python khác:
>>> import re
>>> p = re.compile('[a-z]+')
>>> p
re.compile('[a-z]+')
93 chỉ ra rằng nội dung của nhóm được gọi là tên một lần nữa phải được khớp tại điểm hiện tại. Biểu thức chính quy để tìm từ nhân đôi,
>>> import re
>>> p = re.compile('[a-z]+')
>>> p
re.compile('[a-z]+')
94 cũng có thể được viết là
>>> import re
>>> p = re.compile('[a-z]+')
>>> p
re.compile('[a-z]+')
95:

>>> p = re.compile('ab*', re.IGNORECASE)
9

Asserments LookAhead

Một khẳng định không có chiều rộng khác là khẳng định lookahead. Các khẳng định lookahead có sẵn ở cả hình thức tích cực và tiêu cực, và trông như thế này:

>>> import re
>>> p = re.compile('[a-z]+')
>>> p
re.compile('[a-z]+')
96

Khẳng định nhìn tích cực. Điều này thành công nếu biểu thức có chứa chính quy, được biểu thị ở đây bằng

>>> import re
>>> p = re.compile('[a-z]+')
>>> p
re.compile('[a-z]+')
85, phù hợp thành công tại vị trí hiện tại và không thành công. Nhưng, một khi biểu thức chứa đã được thử, động cơ phù hợp không tiến lên; Phần còn lại của mẫu được thử ngay khi xác nhận bắt đầu.

>>> import re
>>> p = re.compile('[a-z]+')
>>> p
re.compile('[a-z]+')
98

Khẳng định cái nhìn tiêu cực. Đây là điều ngược lại với khẳng định tích cực; Nó thành công nếu biểu thức chứa không phù hợp ở vị trí hiện tại trong chuỗi.

Để làm cho bê tông này, hãy để Lôi nhìn vào một trường hợp mà một cái nhìn là hữu ích. Hãy xem xét một mẫu đơn giản để khớp với tên tệp và chia nó thành một tên cơ sở và một phần mở rộng, được phân tách bằng

>>> import re
>>> p = re.compile('ab*')
>>> p
re.compile('ab*')
00. Ví dụ, trong
>>> p.match("")
>>> print(p.match(""))
None
00,
>>> p.match("")
>>> print(p.match(""))
None
01 là tên cơ sở và
>>> p.match("")
>>> print(p.match(""))
None
02 là tiện ích mở rộng tên tệp.

Mô hình phù hợp với điều này khá đơn giản:

>>> p.match("")
>>> print(p.match(""))
None
03

Lưu ý rằng

>>> import re
>>> p = re.compile('ab*')
>>> p
re.compile('ab*')
00 cần được đối xử đặc biệt bởi vì nó là một metacharacter, do đó, nó bên trong một lớp nhân vật chỉ phù hợp với nhân vật cụ thể đó. Cũng nhận thấy dấu vết
>>> p = re.compile('ab*', re.IGNORECASE)
65; Điều này được thêm vào để đảm bảo rằng tất cả phần còn lại của chuỗi phải được bao gồm trong phần mở rộng. Biểu thức chính quy này phù hợp với
>>> p.match("")
>>> print(p.match(""))
None
06 và
>>> p.match("")
>>> print(p.match(""))
None
07 và
>>> p.match("")
>>> print(p.match(""))
None
08 và
>>> p.match("")
>>> print(p.match(""))
None
09.

Bây giờ, hãy xem xét làm phức tạp vấn đề một chút; Điều gì sẽ xảy ra nếu bạn muốn khớp tên tệp trong đó tiện ích mở rộng không phải là

>>> p.match("")
>>> print(p.match(""))
None
10? Một số nỗ lực không chính xác:

>>> p.match("")
>>> print(p.match(""))
None
11 Nỗ lực đầu tiên ở trên cố gắng loại trừ
>>> p.match("")
>>> print(p.match(""))
None
10 bằng cách yêu cầu ký tự đầu tiên của phần mở rộng không phải là
>>> m = p.match('tempo')
>>> m

6. Điều này là sai, bởi vì mẫu cũng không phù hợp với
>>> p.match("")
>>> print(p.match(""))
None
06.

>>> p.match("")
>>> print(p.match(""))
None
15

Biểu thức trở nên lộn xộn hơn khi bạn cố gắng vá giải pháp đầu tiên bằng cách yêu cầu một trong các trường hợp sau để khớp: ký tự đầu tiên của phần mở rộng isn

>>> m = p.match('tempo')
>>> m

6; Nhân vật thứ hai là
>>> m = p.match('tempo')
>>> m

5; Hoặc nhân vật thứ ba là
>>> p.match("")
>>> print(p.match(""))
None
18. Điều này chấp nhận
>>> p.match("")
>>> print(p.match(""))
None
06 và từ chối
>>> p.match("")
>>> print(p.match(""))
None
07, nhưng nó đòi hỏi một phần mở rộng ba chữ cái và won đã chấp nhận một tên tệp với phần mở rộng hai chữ cái như
>>> p.match("")
>>> print(p.match(""))
None
08. Chúng tôi sẽ làm phức tạp mô hình một lần nữa trong một nỗ lực để sửa chữa nó.

>>> p.match("")
>>> print(p.match(""))
None
22

Trong lần thử thứ ba, các chữ cái thứ hai và thứ ba đều được thực hiện tùy chọn để cho phép các phần mở rộng phù hợp ngắn hơn ba ký tự, chẳng hạn như

>>> p.match("")
>>> print(p.match(""))
None
08.

Các mẫu mà trở nên thực sự phức tạp bây giờ, khiến nó khó đọc và hiểu. Tồi tệ hơn, nếu vấn đề thay đổi và bạn muốn loại trừ cả

>>> p.match("")
>>> print(p.match(""))
None
10 và
>>> p.match("")
>>> print(p.match(""))
None
25 dưới dạng các phần mở rộng, mẫu sẽ còn phức tạp và khó hiểu hơn nữa.

Một cái nhìn tiêu cực cắt giảm tất cả sự nhầm lẫn này:

>>> p.match("")
>>> print(p.match(""))
None
26 LOẠI ĐÁNH GIÁ có nghĩa là: Nếu biểu thức
>>> p.match("")
>>> print(p.match(""))
None
10 không khớp với điểm này, hãy thử phần còn lại của mẫu; Nếu
>>> p.match("")
>>> print(p.match(""))
None
28 không khớp, toàn bộ mẫu sẽ thất bại. Trailing
>>> p = re.compile('ab*', re.IGNORECASE)
65 được yêu cầu để đảm bảo rằng một cái gì đó như
>>> p.match("")
>>> print(p.match(""))
None
30, trong đó phần mở rộng chỉ bắt đầu bằng
>>> p.match("")
>>> print(p.match(""))
None
10, sẽ được cho phép.
>>> p.match("")
>>> print(p.match(""))
None
32 đảm bảo rằng mẫu hoạt động khi có nhiều dấu chấm trong tên tệp.

Không bao gồm một phần mở rộng tên tệp khác bây giờ là dễ dàng; Đơn giản chỉ cần thêm nó như một sự thay thế bên trong khẳng định. Mẫu sau đây loại trừ tên tệp kết thúc trong

>>> p.match("")
>>> print(p.match(""))
None
10 hoặc
>>> p.match("")
>>> print(p.match(""))
None
25:

>>> p.match("")
>>> print(p.match(""))
None
35

Sửa đổi chuỗi

Cho đến thời điểm này, chúng tôi chỉ đơn giản thực hiện các tìm kiếm đối với một chuỗi tĩnh. Các biểu thức thông thường cũng thường được sử dụng để sửa đổi các chuỗi theo nhiều cách khác nhau, sử dụng các phương thức mẫu sau:

Method/Attribute

Mục đích

>>> p.match("")
>>> print(p.match(""))
None
36

Chia chuỗi thành một danh sách, chia nó ở bất cứ nơi nào RE khớp với

>>> p = re.compile('ab*', re.IGNORECASE)
39

Tìm tất cả các chuỗi con trong đó RE khớp và thay thế chúng bằng một chuỗi khác

>>> p.match("")
>>> print(p.match(""))
None
38

Làm điều tương tự như

>>> p = re.compile('ab*', re.IGNORECASE)
39, nhưng trả về chuỗi mới và số lượng thay thế

Chuỗi phân tách

Phương pháp

>>> p.match("")
>>> print(p.match(""))
None
36 của một mẫu phân tách một chuỗi cách nhau bất cứ nơi nào khớp nối lại, trả lại một danh sách các mảnh. Nó tương tự như phương pháp
>>> p.match("")
>>> print(p.match(""))
None
36 của chuỗi nhưng cung cấp tính tổng quát hơn nhiều trong các dấu phân cách mà bạn có thể chia bằng; Chuỗi
>>> p.match("")
>>> print(p.match(""))
None
36 chỉ hỗ trợ chia tách bằng khoảng trắng hoặc bằng một chuỗi cố định. Như bạn đã mong đợi, cũng có một hàm
>>> p.match("")
>>> print(p.match(""))
None
43 ở cấp độ mô-đun.

.Split (Chuỗi [, MaxSplit = 0])split(string[, maxsplit=0])

Chia chuỗi phân chia theo các kết quả của biểu thức chính quy. Nếu chụp dấu ngoặc đơn được sử dụng trong RE, thì nội dung của chúng cũng sẽ được trả lại như một phần của danh sách kết quả. Nếu MAXSplit là khác nhau, tại hầu hết các phân tách MaxSplit được thực hiện.

Bạn có thể giới hạn số lượng phân tách được thực hiện, bằng cách chuyển một giá trị cho MaxSplit. Khi MAXSplit là không khác biệt, tại hầu hết các phân tách MaxSplit sẽ được thực hiện và phần còn lại của chuỗi được trả về làm yếu tố cuối cùng của danh sách. Trong ví dụ sau, dấu phân cách là bất kỳ chuỗi các ký tự không phải là vô hiệu.

>>> import re
>>> p = re.compile('[a-z]+')
>>> p
re.compile('[a-z]+')
0

Đôi khi, bạn không chỉ quan tâm đến văn bản giữa các phân định là gì, mà còn cần biết dấu phân cách là gì. Nếu thu được dấu ngoặc đơn được sử dụng trong RE, thì các giá trị của chúng cũng được trả về như một phần của danh sách. So sánh các cuộc gọi sau:

>>> import re
>>> p = re.compile('[a-z]+')
>>> p
re.compile('[a-z]+')
1

Hàm cấp độ mô-đun

>>> p.match("")
>>> print(p.match(""))
None
43 thêm RE được sử dụng làm đối số đầu tiên, nhưng nếu không thì giống nhau.

>>> import re
>>> p = re.compile('[a-z]+')
>>> p
re.compile('[a-z]+')
2

Tìm kiếm và thay thế Or

Một nhiệm vụ phổ biến khác là tìm tất cả các trận đấu cho một mẫu và thay thế chúng bằng một chuỗi khác. Phương thức

>>> p = re.compile('ab*', re.IGNORECASE)
39 có giá trị thay thế, có thể là một chuỗi hoặc hàm và chuỗi được xử lý.

.sub (thay thế, chuỗi [, đếm = 0])sub(replacement, string[, count=0])

Trả về chuỗi thu được bằng cách thay thế các lần xuất hiện không chồng chéo bên trái của RE trong chuỗi bằng cách thay thế thay thế. Nếu mẫu được tìm thấy, chuỗi được trả về không thay đổi.

Số lượng đối số tùy chọn là số lượng tối đa của các lần xuất hiện mẫu được thay thế; Đếm phải là một số nguyên không âm. Giá trị mặc định của 0 có nghĩa là thay thế tất cả các lần xuất hiện.

Ở đây, một ví dụ đơn giản về việc sử dụng phương pháp

>>> p = re.compile('ab*', re.IGNORECASE)
39. Nó thay thế tên màu bằng từ
>>> p.match("")
>>> print(p.match(""))
None
47:

>>> import re
>>> p = re.compile('[a-z]+')
>>> p
re.compile('[a-z]+')
3

Phương thức

>>> p.match("")
>>> print(p.match(""))
None
38 thực hiện cùng một công việc, nhưng trả về 2-tuple chứa giá trị chuỗi mới và số lượng thay thế được thực hiện:

>>> import re
>>> p = re.compile('[a-z]+')
>>> p
re.compile('[a-z]+')
4

Các trận đấu trống chỉ được thay thế khi họ không liền kề với trận đấu trống trước đó.

>>> import re
>>> p = re.compile('[a-z]+')
>>> p
re.compile('[a-z]+')
5

Nếu thay thế là một chuỗi, bất kỳ dấu gạch chéo ngược nào đều thoát trong đó được xử lý. Đó là,

>>> p.match("")
>>> print(p.match(""))
None
49 được chuyển đổi thành một ký tự mới,
>>> p.match("")
>>> print(p.match(""))
None
50 được chuyển đổi thành một trở lại vận chuyển, v.v. Những trốn thoát chưa biết như
>>> import re
>>> p = re.compile('[a-z]+')
>>> p
re.compile('[a-z]+')
74 bị bỏ lại một mình. Các bản sao lưu, chẳng hạn như
>>> p.match("")
>>> print(p.match(""))
None
52, được thay thế bằng chuỗi con phù hợp với nhóm tương ứng trong RE. Điều này cho phép bạn kết hợp các phần của văn bản gốc trong chuỗi thay thế kết quả.

Ví dụ này khớp với từ

>>> p.match("")
>>> print(p.match(""))
None
53 theo sau là một chuỗi được đặt trong
>>> p.match("")
>>> print(p.match(""))
None
54,
>>> p.match("")
>>> print(p.match(""))
None
55 và thay đổi
>>> p.match("")
>>> print(p.match(""))
None
53 thành
>>> p.match("")
>>> print(p.match(""))
None
57:

>>> import re
>>> p = re.compile('[a-z]+')
>>> p
re.compile('[a-z]+')
6

Ngoài ra, còn có một cú pháp để đề cập đến các nhóm được đặt tên theo định nghĩa của cú pháp

>>> import re
>>> p = re.compile('[a-z]+')
>>> p
re.compile('[a-z]+')
88.
>>> p.match("")
>>> print(p.match(""))
None
59 sẽ sử dụng chuỗi con phù hợp với nhóm có tên
>>> p.match("")
>>> print(p.match(""))
None
60 và
>>> p.match("")
>>> print(p.match(""))
None
61 sử dụng số nhóm tương ứng. Do đó,
>>> p.match("")
>>> print(p.match(""))
None
62 tương đương với
>>> p.match("")
>>> print(p.match(""))
None
63, nhưng không phải là mơ hồ trong một chuỗi thay thế như
>>> p.match("")
>>> print(p.match(""))
None
64. .

>>> import re
>>> p = re.compile('[a-z]+')
>>> p
re.compile('[a-z]+')
7

Thay thế cũng có thể là một chức năng, giúp bạn kiểm soát nhiều hơn. Nếu thay thế là một hàm, hàm được gọi cho mọi lần xuất hiện không chồng chéo của mẫu. Trên mỗi cuộc gọi, hàm được chuyển một đối số đối tượng khớp cho trận đấu và có thể sử dụng thông tin này để tính toán chuỗi thay thế mong muốn và trả về nó.match object argument for the match and can use this information to compute the desired replacement string and return it.

Trong ví dụ sau, hàm thay thế chuyển số thập phân thành thập lục phân:

>>> import re
>>> p = re.compile('[a-z]+')
>>> p
re.compile('[a-z]+')
8

Khi sử dụng hàm

>>> p.match("")
>>> print(p.match(""))
None
67 cấp độ mô-đun, mẫu được truyền làm đối số đầu tiên. Mẫu có thể được cung cấp dưới dạng đối tượng hoặc dưới dạng chuỗi; Nếu bạn cần chỉ định các cờ biểu thức thông thường, bạn phải sử dụng một đối tượng mẫu làm tham số đầu tiên hoặc sử dụng các bộ sửa đổi nhúng trong chuỗi mẫu, ví dụ:
>>> p.match("")
>>> print(p.match(""))
None
68 Trả về
>>> p.match("")
>>> print(p.match(""))
None
69.

Những vấn đề chung¶

Biểu thức chính quy là một công cụ mạnh mẽ cho một số ứng dụng, nhưng trong một số cách, hành vi của họ không trực quan và đôi khi họ không hành xử theo cách bạn có thể mong đợi. Phần này sẽ chỉ ra một số cạm bẫy phổ biến nhất.

Sử dụng các phương thức chuỗi

Đôi khi sử dụng mô -đun

>>> p.match("")
>>> print(p.match(""))
None
5 là một sai lầm. Nếu bạn phù hợp với một chuỗi cố định hoặc một lớp ký tự duy nhất và bạn không sử dụng bất kỳ tính năng
>>> p.match("")
>>> print(p.match(""))
None
5 nào như cờ
>>> p = re.compile('ab*', re.IGNORECASE)
42, thì có thể không cần phải có toàn bộ sức mạnh của các biểu thức thông thường. Các chuỗi có một số phương pháp để thực hiện các hoạt động với các chuỗi cố định và chúng thường nhanh hơn nhiều, bởi vì việc triển khai là một vòng C nhỏ duy nhất mà Lọ được tối ưu hóa cho mục đích, thay vì động cơ biểu thức chính quy lớn hơn, tổng quát hơn.

Một ví dụ có thể là thay thế một chuỗi cố định bằng một chuỗi khác; Ví dụ: bạn có thể thay thế

>>> p.match("")
>>> print(p.match(""))
None
73 bằng
>>> p.match("")
>>> print(p.match(""))
None
74.
>>> p.match("")
>>> print(p.match(""))
None
67 có vẻ như là chức năng sử dụng cho việc này, nhưng hãy xem xét phương pháp
>>> p.match("")
>>> print(p.match(""))
None
76. Lưu ý rằng
>>> p.match("")
>>> print(p.match(""))
None
76 cũng sẽ thay thế
>>> p.match("")
>>> print(p.match(""))
None
73 Các từ bên trong, biến
>>> p.match("")
>>> print(p.match(""))
None
79 thành
>>> p.match("")
>>> print(p.match(""))
None
80, nhưng re re
>>> p.match("")
>>> print(p.match(""))
None
73 ngây thơ cũng sẽ làm điều đó. .

Một nhiệm vụ phổ biến khác là xóa mọi lần xuất hiện của một ký tự từ một chuỗi hoặc thay thế nó bằng một ký tự đơn khác. Bạn có thể làm điều này với một cái gì đó như

>>> p.match("")
>>> print(p.match(""))
None
85, nhưng
>>> p.match("")
>>> print(p.match(""))
None
86 có khả năng thực hiện cả hai nhiệm vụ và sẽ nhanh hơn bất kỳ hoạt động biểu thức chính quy nào có thể.

Nói tóm lại, trước khi chuyển sang mô -đun

>>> p.match("")
>>> print(p.match(""))
None
5, hãy xem xét liệu vấn đề của bạn có thể được giải quyết bằng phương pháp chuỗi nhanh hơn và đơn giản hơn hay không.

khớp () so với tìm kiếm () ¶

Hàm

>>> import re
>>> p = re.compile('ab*')
>>> p
re.compile('ab*')
99 chỉ kiểm tra xem RE có khớp ở đầu chuỗi trong khi
>>> p = re.compile('ab*', re.IGNORECASE)
00 sẽ quét về phía trước qua chuỗi cho một trận đấu không. Nó rất quan trọng để ghi nhớ sự khác biệt này. Hãy nhớ rằng,
>>> import re
>>> p = re.compile('ab*')
>>> p
re.compile('ab*')
99 sẽ chỉ báo cáo một trận đấu thành công sẽ bắt đầu ở 0; Nếu trận đấu sẽ bắt đầu ở 0,
>>> import re
>>> p = re.compile('ab*')
>>> p
re.compile('ab*')
99 sẽ không báo cáo.

>>> import re
>>> p = re.compile('[a-z]+')
>>> p
re.compile('[a-z]+')
9

Mặt khác,

>>> p = re.compile('ab*', re.IGNORECASE)
00 sẽ quét về phía trước qua chuỗi, báo cáo trận đấu đầu tiên mà nó tìm thấy.

>>> p.match("")
>>> print(p.match(""))
None
0

Đôi khi, bạn sẽ bị cám dỗ để tiếp tục sử dụng

>>> p.match("")
>>> print(p.match(""))
None
93 và chỉ cần thêm
>>> p.match("")
>>> print(p.match(""))
None
94 vào mặt trước của RE. Thay vào đó, hãy chống lại sự cám dỗ này và sử dụng
>>> p.match("")
>>> print(p.match(""))
None
95. Trình biên dịch biểu thức chính quy thực hiện một số phân tích RES để tăng tốc quá trình tìm kiếm một trận đấu. Một phân tích như vậy đưa ra những gì nhân vật đầu tiên của một trận đấu phải là gì; Ví dụ: một mẫu bắt đầu bằng
>>> p.match("")
>>> print(p.match(""))
None
96 phải khớp với bắt đầu với
>>> p.match("")
>>> print(p.match(""))
None
97. Phân tích cho phép động cơ nhanh chóng quét qua chuỗi tìm kiếm ký tự bắt đầu, chỉ thử toàn bộ trận đấu nếu tìm thấy
>>> p.match("")
>>> print(p.match(""))
None
97.

Thêm

>>> p.match("")
>>> print(p.match(""))
None
94 đánh bại tối ưu hóa này, yêu cầu quét vào cuối chuỗi và sau đó quay lại để tìm một trận đấu cho phần còn lại của RE. Sử dụng
>>> p.match("")
>>> print(p.match(""))
None
95 thay thế.

Tham lam so với không tham lam

Khi lặp lại một biểu thức chính quy, như trong

>>> m = p.match('tempo')
>>> m

01, hành động kết quả là tiêu thụ càng nhiều mô hình càng tốt. Thực tế này thường cắn bạn khi bạn đang cố gắng phù hợp với một cặp phân tích cân bằng, chẳng hạn như giá đỡ góc xung quanh thẻ HTML. Mẫu ngây thơ để phù hợp với một thẻ HTML duy nhất không hoạt động vì tính chất tham lam của
>>> p.match("")
>>> print(p.match(""))
None
94.

>>> p.match("")
>>> print(p.match(""))
None
1

RE khớp với

>>> m = p.match('tempo')
>>> m

03 trong
>>> m = p.match('tempo')
>>> m

04 và
>>> p.match("")
>>> print(p.match(""))
None
94 tiêu thụ phần còn lại của chuỗi. Mặc dù vậy, vẫn còn nhiều hơn nữa trong RE, và
>>> m = p.match('tempo')
>>> m

06 có thể khớp với cuối chuỗi, do đó, công cụ biểu thức thông thường phải quay lại ký tự cho đến khi nó tìm thấy một trận đấu cho
>>> m = p.match('tempo')
>>> m

06. Trận đấu cuối cùng kéo dài từ
>>> m = p.match('tempo')
>>> m

03 trong
>>> m = p.match('tempo')
>>> m

04 đến
>>> m = p.match('tempo')
>>> m

10 trong
>>> m = p.match('tempo')
>>> m

11, đó là những gì bạn muốn.

Trong trường hợp này, giải pháp là sử dụng các bộ định lượng không màu xanh lá cây

>>> m = p.match('tempo')
>>> m

12,
>>> m = p.match('tempo')
>>> m

13,
>>> m = p.match('tempo')
>>> m

14 hoặc
>>> m = p.match('tempo')
>>> m

15, phù hợp với văn bản ít nhất có thể. Trong ví dụ trên,
>>> m = p.match('tempo')
>>> m

10 được thử ngay sau khi
>>> m = p.match('tempo')
>>> m

03 đầu tiên kết hợp và khi nó bị hỏng, động cơ sẽ tiến lên một ký tự tại một thời điểm, thử lại
>>> m = p.match('tempo')
>>> m

10 ở mỗi bước. Điều này chỉ tạo ra kết quả đúng:

>>> p.match("")
>>> print(p.match(""))
None
2

. Xử lý tất cả các trường hợp có thể, các mẫu sẽ rất phức tạp. Sử dụng mô -đun phân tích cú pháp HTML hoặc XML cho các tác vụ đó.)

Sử dụng Re.verbose¶

Đến bây giờ, bạn có thể nhận thấy rằng các biểu thức thông thường là một ký hiệu rất nhỏ gọn, nhưng chúng không thể đọc được khủng khiếp. Res của sự phức tạp vừa phải có thể trở thành các bộ sưu tập dài các dấu gạch chéo ngược, dấu ngoặc đơn và metacharacters, khiến chúng khó đọc và hiểu.

Đối với độ phân giải như vậy, việc chỉ định cờ

>>> p = re.compile('ab*', re.IGNORECASE)
44 khi biên dịch biểu thức thông thường có thể hữu ích, bởi vì nó cho phép bạn định dạng biểu thức thông thường rõ ràng hơn.

Cờ

>>> p = re.compile('ab*', re.IGNORECASE)
44 có một số hiệu ứng. Whitespace trong biểu thức chính quy không phải là bên trong một lớp nhân vật bị bỏ qua. Điều này có nghĩa là một biểu thức như
>>> m = p.match('tempo')
>>> m

21 tương đương với
>>> m = p.match('tempo')
>>> m

22 không thể đọc được, nhưng
>>> m = p.match('tempo')
>>> m

23 vẫn sẽ khớp với các ký tự
>>> m.group()
'tempo'
>>> m.start(), m.end()
(0, 5)
>>> m.span()
(0, 5)
2,
>>> import re
>>> p = re.compile('ab*')
>>> p
re.compile('ab*')
17 hoặc một không gian. Ngoài ra, bạn cũng có thể đặt nhận xét bên trong một RE; Nhận xét mở rộng từ một ký tự
>>> m = p.match('tempo')
>>> m

26 sang dòng mới tiếp theo. Khi được sử dụng với các chuỗi được trích xuất ba, điều này cho phép RES được định dạng gọn gàng hơn:

>>> p.match("")
>>> print(p.match(""))
None
3

Điều này dễ đọc hơn nhiều so với:

>>> p.match("")
>>> print(p.match(""))
None
4

Nhận xét¶

Biểu thức thường xuyên là một chủ đề phức tạp. Tài liệu này có giúp bạn hiểu chúng không? Có những phần không rõ ràng, hoặc những vấn đề bạn gặp phải mà người sói được bao phủ ở đây? Nếu vậy, xin vui lòng gửi đề xuất để cải thiện cho tác giả.

Cuốn sách hoàn chỉnh nhất về các cách diễn đạt thường xuyên là gần như chắc chắn là Jeffrey Friedl, làm chủ các biểu thức thông thường, được xuất bản bởi O hèReilly. Thật không may, nó chỉ tập trung vào hương vị Perl và Java, của các biểu thức thông thường, và không chứa bất kỳ tài liệu Python nào, vì vậy nó đã giành được hữu ích như một tài liệu tham khảo cho lập trình trong Python. (Phiên bản đầu tiên bao gồm mô-đun

>>> m = p.match('tempo')
>>> m

27 đã được loại bỏ, đã giành được giúp bạn rất nhiều.) Hãy xem xét kiểm tra nó từ thư viện của bạn.