Thông báo: Download 4 khóa học Python từ cơ bản đến nâng cao tại đây.
Các nhóm Capturing trong regex của Python
Trong bài viết này, bạn sẽ tìm hiểu về các nhóm capturing (capturing groups) trong regex của Python. Nhóm capturing giúp bạn tạo ra các nhóm con trong một kết quả khớp, từ đó dễ dàng trích xuất và xử lý các phần cụ thể của chuỗi khớp. Việc hiểu và sử dụng hiệu quả các nhóm capturing là một kỹ năng quan trọng khi làm việc với các biểu thức chính quy, giúp tăng cường khả năng phân tích và thao tác chuỗi trong Python.
Giới thiệu về các nhóm capturing trong regex của Python
Giả sử bạn có đường dẫn sau hiển thị tin tức với id 100 trên một trang web:
news/100
Biểu thức chính quy sau sẽ khớp với đường dẫn trên:
\w+/\d+
Lưu ý rằng biểu thức chính quy này cũng khớp với bất kỳ đường dẫn nào bắt đầu bằng một hoặc nhiều ký tự từ, ví dụ: posts, todos, v.v., không chỉ riêng news.
Bài viết này được đăng tại [free tuts .net]
Trong mẫu này:
\w+
là một tập hợp ký tự từ với lượng từ (+) khớp với một hoặc nhiều ký tự từ./
khớp với ký tự dấu gạch chéo/
.\d+
là một tập hợp ký tự số với lượng từ (+) khớp với một hoặc nhiều chữ số.
Chương trình sau sử dụng mẫu \w+/\d+
để khớp với chuỗi 'news/100':
import re s = 'news/100' pattern = '\w+/\d+' matches = re.finditer(pattern, s) for match in matches: print(match)
Kết quả:
<re.Match object; span=(0, 8), match='news/100'>
Nó cho thấy một kết quả khớp như mong đợi.
Để lấy id từ đường dẫn, bạn sử dụng một nhóm capturing . Để định nghĩa một nhóm capturing cho một mẫu, bạn đặt quy tắc trong dấu ngoặc đơn:
(rule)
Trong mẫu này, chúng ta đặt quy tắc \d+
bên trong dấu ngoặc đơn ()
. Nếu bạn chạy chương trình với mẫu mới, bạn sẽ thấy rằng nó hiển thị một kết quả khớp:
import re s = 'news/100' pattern = '\w+/(\d+)' matches = re.finditer(pattern, s) for match in matches: print(match)
Kết quả:
<re.Match object; span=(0, 8), match='news/100'>
Để lấy các nhóm capturing từ một kết quả khớp, bạn sử dụng phương thức group()
của đối tượng Match
:
match.group(index)
group(0)
sẽ trả về toàn bộ kết quả khớp, trong khi group(1)
, group(2)
, v.v., sẽ trả về nhóm đầu tiên, thứ hai,...
Thuộc tính lastindex
của đối tượng Match
trả về chỉ số cuối cùng của tất cả các nhóm con. Chương trình sau hiển thị toàn bộ kết quả khớp (group(0)
) và tất cả các nhóm con:
import re s = 'news/100' pattern = '\w+/(\d+)' matches = re.finditer(pattern, s) for match in matches: for index in range(0, match.lastindex + 1): print(match.group(index))
Kết quả:
news/100 100
Trong kết quả, news/100
là toàn bộ kết quả khớp trong khi 100
là nhóm con.
Nếu bạn muốn capturing cả tài nguyên (news) trong đường dẫn (news/100), bạn có thể tạo thêm một nhóm capturing như sau:
(\w+)/(\d+)
Trong mẫu này, chúng ta có hai nhóm capturing, một cho \w+
và một cho \d+
. Chương trình sau hiển thị toàn bộ kết quả khớp và tất cả các nhóm con:
import re s = 'news/100' pattern = '(\w+)/(\d+)' matches = re.finditer(pattern, s) for match in matches: for index in range(0, match.lastindex + 1): print(match.group(index))
Kết quả:
news/100 news 100
Trong kết quả, news/100
là toàn bộ kết quả khớp trong khi news
và 100
là các nhóm con.
Nhóm capturing có tên trong regex của Python
Mặc định, bạn có thể truy cập một nhóm con trong một kết quả khớp bằng chỉ số, ví dụ, match.group(1)
. Đôi khi, truy cập một nhóm con bằng một tên có ý nghĩa sẽ thuận tiện hơn.
Bạn sử dụng nhóm capturing có tên để gán tên cho một nhóm. Cú pháp sau cho phép bạn gán tên cho một nhóm capturing :
(?P<name>rule)
Trong cú pháp này:
()
chỉ ra một nhóm capturing .?P<name>
chỉ định tên của nhóm capturing .rule
là một quy tắc trong mẫu.
Ví dụ, nhóm sau tạo các tên:
(?P<resource>\w+)/(?P<id>\d+)
Trong cú pháp này, resource
là tên cho nhóm capturing đầu tiên và id
là tên cho nhóm capturing thứ hai.
Để lấy tất cả các nhóm con có tên của một kết quả khớp, bạn sử dụng phương thức groupdict()
của đối tượng Match
. Ví dụ:
import re s = 'news/100' pattern = '(?P<resource>\w+)/(?P<id>\d+)' matches = re.finditer(pattern, s) for match in matches: print(match.groupdict())
Kết quả:
{'resource': 'news', 'id': '100'}
Trong ví dụ này, phương thức groupdict()
trả về một từ điển, trong đó các khóa là tên của các nhóm và giá trị là các nhóm con.
Ví dụ thêm về nhóm capturing có tên
Mẫu sau:
\w+/\d{4}/\d{2}/\d{2}
khớp với đường dẫn:
news/2021/12/31
Và bạn có thể thêm các nhóm capturing có tên vào mẫu như sau:
(?P<resource>\w+)/(?P<year>\d{4})/(?P<month>\d{1,2})/(?P<day>\d{1,2})
Chương trình sau sử dụng mẫu này để khớp với đường dẫn và hiển thị tất cả các nhóm con:
import re s = 'news/2021/12/31' pattern = '(?P<resource>\w+)/(?P<year>\d{4})/(?P<month>\d{1,2})/(?P<day>\d{1,2})' matches = re.finditer(pattern, s) for match in matches: print(match.groupdict())
Kết quả:
{'resource': 'news', 'year': '2021', 'month': '12', 'day': '31'}
Kết bài
việc sử dụng các nhóm capturing trong regex của Python mang lại nhiều lợi ích trong việc phân tích và xử lý chuỗi. Bạn có thể tạo nhóm capturing bằng cách đặt quy tắc của một mẫu trong dấu ngoặc đơn (), sử dụng phương thức group() của đối tượng Match để lấy nhóm con bằng chỉ số, hoặc sử dụng (?P<name>rule) để tạo nhóm capturing có tên cho quy tắc trong mẫu. Cuối cùng, phương thức groupdict() của đối tượng Match giúp bạn lấy các nhóm con có tên dưới dạng từ điển, giúp việc xử lý dữ liệu trở nên dễ dàng và hiệu quả hơn.