Perl - Biểu thức chính quy
Biểu thức chính quy là một chuỗi ký tự xác định mẫu hoặc các mẫu bạn đang xem. Cú pháp của các biểu thức chính quy trong Perl rất giống với những gì bạn sẽ tìm thấy trong các biểu thức chính quy khác. Các chương trình hỗ trợ, chẳng hạn nhưsed, grepvà awk.
Phương pháp cơ bản để áp dụng một biểu thức chính quy là sử dụng các toán tử liên kết mẫu = ~ và !~. Toán tử đầu tiên là toán tử kiểm tra và gán.
Có ba toán tử biểu thức chính quy trong Perl.
- Khớp biểu thức chính quy - m //
- Biểu thức chính quy thay thế - s ///
- Chuyển ngữ cụm từ thông dụng - tr ///
Các dấu gạch chéo về phía trước trong mỗi trường hợp đóng vai trò là dấu phân cách cho biểu thức chính quy (regex) mà bạn đang chỉ định. Nếu bạn cảm thấy thoải mái với bất kỳ dấu phân cách nào khác, thì bạn có thể sử dụng thay cho dấu gạch chéo.
Người điều hành trận đấu
Toán tử so khớp, m //, được sử dụng để so khớp một chuỗi hoặc câu lệnh với một biểu thức chính quy. Ví dụ: để khớp chuỗi ký tự "foo" với thanh $ vô hướng, bạn có thể sử dụng một câu lệnh như sau:
#!/usr/bin/perl
$bar = "This is foo and again foo";
if ($bar =~ /foo/) {
print "First time is matching\n";
} else {
print "First time is not matching\n";
}
$bar = "foo";
if ($bar =~ /foo/) {
print "Second time is matching\n";
} else {
print "Second time is not matching\n";
}
Khi chương trình trên được thực thi, nó tạo ra kết quả sau:
First time is matching
Second time is matching
M // thực sự hoạt động theo cùng kiểu với dãy toán tử q //. Bạn có thể sử dụng bất kỳ tổ hợp nào của các ký tự đối sánh tự nhiên để đóng vai trò là dấu phân cách cho biểu thức. Ví dụ: m {}, m () và m> <đều hợp lệ. Vì vậy, ví dụ trên có thể được viết lại như sau:
#!/usr/bin/perl
$bar = "This is foo and again foo";
if ($bar =~ m[foo]) {
print "First time is matching\n";
} else {
print "First time is not matching\n";
}
$bar = "foo";
if ($bar =~ m{foo}) {
print "Second time is matching\n";
} else {
print "Second time is not matching\n";
}
Bạn có thể bỏ qua m khỏi m // nếu các dấu phân cách là dấu gạch chéo về phía trước, nhưng đối với tất cả các dấu phân cách khác, bạn phải sử dụng tiền tố m.
Lưu ý rằng toàn bộ biểu thức đối sánh, đó là biểu thức ở bên trái của = ~ hoặc! ~ Và toán tử đối sánh, trả về true (trong ngữ cảnh vô hướng) nếu biểu thức khớp. Do đó, tuyên bố -
$true = ($foo =~ m/foo/);
sẽ đặt $ true thành 1 nếu $ foo khớp với regex hoặc 0 nếu khớp không thành công. Trong ngữ cảnh danh sách, đối sánh trả về nội dung của bất kỳ biểu thức được nhóm nào. Ví dụ: khi trích xuất giờ, phút và giây từ một chuỗi thời gian, chúng ta có thể sử dụng:
my ($hours, $minutes, $seconds) = ($time =~ m/(\d+):(\d+):(\d+)/);
Công cụ sửa đổi toán tử đối sánh
Toán tử đối sánh hỗ trợ tập hợp các bổ ngữ của riêng nó. Công cụ sửa đổi / g cho phép đối sánh toàn cục. Bổ ngữ / i sẽ làm cho so khớp không phân biệt chữ hoa và chữ thường. Đây là danh sách đầy đủ các bổ ngữ
Sr.No. | Công cụ sửa đổi & mô tả |
---|---|
1 | i Làm cho đối sánh không phân biệt chữ hoa và chữ thường. |
2 | m Chỉ định rằng nếu chuỗi có ký tự xuống dòng hoặc ký tự xuống dòng, các toán tử ^ và $ bây giờ sẽ khớp với ranh giới dòng mới, thay vì ranh giới chuỗi. |
3 | o Chỉ đánh giá biểu thức một lần. |
4 | s Cho phép sử dụng. để khớp với một ký tự dòng mới. |
5 | x Cho phép bạn sử dụng khoảng trắng trong biểu thức cho rõ ràng. |
6 | g Toàn cầu tìm thấy tất cả các trận đấu. |
7 | cg Cho phép tiếp tục tìm kiếm ngay cả sau khi kết hợp toàn cầu không thành công. |
Chỉ phù hợp một lần
Ngoài ra còn có một phiên bản đơn giản hơn của toán tử so khớp -? PATTERN? nhà điều hành. Về cơ bản, toán tử này giống với toán tử m // ngoại trừ việc nó chỉ khớp một lần trong chuỗi mà bạn đang tìm kiếm giữa mỗi lần gọi để đặt lại.
Ví dụ: bạn có thể sử dụng điều này để lấy các phần tử đầu tiên và cuối cùng trong danh sách -
#!/usr/bin/perl
@list = qw/food foosball subeo footnote terfoot canic footbrdige/;
foreach (@list) {
$first = $1 if /(foo.*?)/;
$last = $1 if /(foo.*)/;
}
print "First: $first, Last: $last\n";
Khi chương trình trên được thực thi, nó tạo ra kết quả sau:
First: foo, Last: footbrdige
Biến biểu thức chính quy
Các biến biểu thức chính quy bao gồm $, chứa bất kỳ thứ gì mà trận đấu nhóm cuối cùng phù hợp; $&, chứa toàn bộ chuỗi được so khớp; $`, chứa mọi thứ trước chuỗi được so khớp; và$', chứa mọi thứ sau chuỗi được so khớp. Đoạn mã sau minh họa kết quả:
#!/usr/bin/perl
$string = "The food is in the salad bar";
$string =~ m/foo/;
print "Before: $`\n";
print "Matched: $&\n";
print "After: $'\n";
Khi chương trình trên được thực thi, nó tạo ra kết quả sau:
Before: The
Matched: foo
After: d is in the salad bar
Người điều hành thay thế
Toán tử thay thế, s ///, thực sự chỉ là một phần mở rộng của toán tử so khớp cho phép bạn thay thế văn bản được so khớp bằng một số văn bản mới. Dạng cơ bản của toán tử là -
s/PATTERN/REPLACEMENT/;
PATTERN là biểu thức chính quy cho văn bản mà chúng tôi đang tìm kiếm. REPLACEMENT là một đặc tả cho văn bản hoặc biểu thức chính quy mà chúng tôi muốn sử dụng để thay thế văn bản được tìm thấy. Ví dụ: chúng tôi có thể thay thế tất cả các lần xuất hiện củadog với cat sử dụng biểu thức chính quy sau:
#/user/bin/perl
$string = "The cat sat on the mat";
$string =~ s/cat/dog/;
print "$string\n";
Khi chương trình trên được thực thi, nó tạo ra kết quả sau:
The dog sat on the mat
Công cụ sửa đổi toán tử thay thế
Đây là danh sách tất cả các từ bổ nghĩa được sử dụng với toán tử thay thế.
Sr.No. | Công cụ sửa đổi & mô tả |
---|---|
1 | i Làm cho đối sánh không phân biệt chữ hoa và chữ thường. |
2 | m Chỉ định rằng nếu chuỗi có ký tự xuống dòng hoặc ký tự xuống dòng, các toán tử ^ và $ bây giờ sẽ khớp với ranh giới dòng mới, thay vì ranh giới chuỗi. |
3 | o Chỉ đánh giá biểu thức một lần. |
4 | s Cho phép sử dụng. để khớp với một ký tự dòng mới. |
5 | x Cho phép bạn sử dụng khoảng trắng trong biểu thức cho rõ ràng. |
6 | g Thay thế tất cả các lần xuất hiện của biểu thức tìm được bằng văn bản thay thế. |
7 | e Đánh giá sự thay thế như thể nó là một câu lệnh Perl và sử dụng giá trị trả về của nó làm văn bản thay thế. |
Nhà điều hành dịch thuật
Bản dịch tương tự, nhưng không giống với các nguyên tắc thay thế, nhưng không giống như thay thế, bản dịch (hoặc chuyển ngữ) không sử dụng cụm từ thông dụng để tìm kiếm các giá trị thay thế. Các toán tử dịch là -
tr/SEARCHLIST/REPLACEMENTLIST/cds
y/SEARCHLIST/REPLACEMENTLIST/cds
Bản dịch thay thế tất cả các lần xuất hiện của các ký tự trong DANH SÁCH TÌM KIẾM bằng các ký tự tương ứng trong DANH SÁCH THAY THẾ. Ví dụ: sử dụng "The cat sat on the mat." chuỗi chúng tôi đã sử dụng trong chương này -
#/user/bin/perl
$string = 'The cat sat on the mat';
$string =~ tr/a/o/;
print "$string\n";
Khi chương trình trên được thực thi, nó tạo ra kết quả sau:
The cot sot on the mot.
Phạm vi Perl tiêu chuẩn cũng có thể được sử dụng, cho phép bạn chỉ định phạm vi ký tự theo chữ cái hoặc giá trị số. Để thay đổi trường hợp của chuỗi, bạn có thể sử dụng cú pháp sau thay chouc chức năng.
$string =~ tr/a-z/A-Z/;
Công cụ sửa đổi toán tử dịch
Sau đây là danh sách các toán tử liên quan đến dịch thuật.
Sr.No. | Công cụ sửa đổi & mô tả |
---|---|
1 | c Phần bổ sung TÌM KIẾM. |
2 | d Xóa các ký tự được tìm thấy nhưng không có vị trí. |
3 | s Dấu gạch chéo trùng lặp các ký tự được thay thế. |
Công cụ sửa đổi / d sẽ xóa các ký tự khớp với DANH SÁCH TÌM KIẾM không có mục nhập tương ứng trong DANH SÁCH THAY THẾ. Ví dụ -
#!/usr/bin/perl
$string = 'the cat sat on the mat.';
$string =~ tr/a-z/b/d;
print "$string\n";
Khi chương trình trên được thực thi, nó tạo ra kết quả sau:
b b b.
Công cụ sửa đổi cuối cùng, / s, loại bỏ các chuỗi ký tự trùng lặp đã được thay thế, vì vậy -
#!/usr/bin/perl
$string = 'food';
$string = 'food';
$string =~ tr/a-z/a-z/s;
print "$string\n";
Khi chương trình trên được thực thi, nó tạo ra kết quả sau:
fod
Biểu thức chính quy phức tạp hơn
Bạn không chỉ phải khớp trên các chuỗi cố định. Trên thực tế, bạn có thể so khớp bất cứ điều gì bạn có thể mơ ước bằng cách sử dụng các cụm từ thông dụng phức tạp hơn. Đây là một bảng gian lận nhanh -
Bảng sau liệt kê cú pháp biểu thức chính quy có sẵn trong Python.
Sr.No. | Mô hình & Mô tả |
---|---|
1 | ^ Đối sánh đầu dòng. |
2 | $ Đối sánh với cuối dòng. |
3 | . Khớp với bất kỳ ký tự đơn nào ngoại trừ dòng mới. Sử dụng tùy chọn m cũng cho phép nó khớp với dòng mới. |
4 | [...] Khớp bất kỳ ký tự đơn nào trong ngoặc. |
5 | [^...] Đối sánh bất kỳ ký tự đơn nào không có trong dấu ngoặc. |
6 | * Khớp với 0 hoặc nhiều lần xuất hiện của biểu thức trước. |
7 | + Khớp với 1 hoặc nhiều lần xuất hiện của biểu thức trước. |
số 8 | ? Khớp với 0 hoặc 1 lần xuất hiện của biểu thức trước. |
9 | { n} Khớp chính xác n số lần xuất hiện của biểu thức trước. |
10 | { n,} Khớp với n hoặc nhiều lần xuất hiện của biểu thức trước. |
11 | { n, m} Khớp ít nhất n và nhiều nhất m lần xuất hiện của biểu thức trước. |
12 | a| b Đối sánh với a hoặc b. |
13 | \w Khớp các ký tự từ. |
14 | \W Đối sánh các ký tự không phải từ khóa. |
15 | \s Khớp khoảng trắng. Tương đương với [\ t \ n \ r \ f]. |
16 | \S Khớp với khoảng trắng. |
17 | \d Khớp các chữ số. Tương đương với [0-9]. |
18 | \D Phù hợp với nondigits. |
19 | \A Đối sánh với phần đầu của chuỗi. |
20 | \Z Đối sánh với cuối chuỗi. Nếu một dòng mới tồn tại, nó sẽ khớp ngay trước dòng mới. |
21 | \z Đối sánh với cuối chuỗi. |
22 | \G Các trận đấu chỉ kết thúc trận đấu cuối cùng. |
23 | \b Khớp các ranh giới từ khi nằm ngoài dấu ngoặc. Khớp với khoảng trắng lùi (0x08) khi bên trong dấu ngoặc. |
24 | \B Đối sánh các ranh giới không có từ khóa. |
25 | \n, \t, etc. Khớp với dòng mới, dấu xuống dòng, tab, v.v. |
26 | \1...\9 Đối sánh biểu thức con được nhóm thứ n. |
27 | \10 Đối sánh biểu thức con được nhóm thứ n nếu nó đã khớp. Mặt khác đề cập đến biểu diễn bát phân của mã ký tự. |
28 | [aeiou] Khớp một ký tự trong tập hợp đã cho |
29 | [^aeiou] Khớp một ký tự bên ngoài tập hợp đã cho |
^ Metacharacter khớp với phần đầu của chuỗi và $ metasymbol khớp với phần cuối của chuỗi. Dưới đây là một số ví dụ ngắn gọn.
# nothing in the string (start and end are adjacent)
/^$/
# a three digits, each followed by a whitespace
# character (eg "3 4 5 ")
/(\d\s) {3}/
# matches a string in which every
# odd-numbered letter is a (eg "abacadaf")
/(a.)+/
# string starts with one or more digits
/^\d+/
# string that ends with one or more digits
/\d+$/
Hãy xem một ví dụ khác.
#!/usr/bin/perl
$string = "Cats go Catatonic\nWhen given Catnip";
($start) = ($string =~ /\A(.*?) /);
@lines = $string =~ /^(.*?) /gm;
print "First word: $start\n","Line starts: @lines\n";
Khi chương trình trên được thực thi, nó tạo ra kết quả sau:
First word: Cats
Line starts: Cats When
Các ranh giới phù hợp
Các \bkhớp ở bất kỳ ranh giới từ nào, như được xác định bởi sự khác biệt giữa lớp \ w và lớp \ W. Bởi vì \ w bao gồm các ký tự cho một từ và \ W ngược lại, điều này thường có nghĩa là sự kết thúc của một từ. Các\Bkhẳng định khớp với bất kỳ vị trí nào không phải là ranh giới từ. Ví dụ -
/\bcat\b/ # Matches 'the cat sat' but not 'cat on the mat'
/\Bcat\B/ # Matches 'verification' but not 'the cat on the mat'
/\bcat\B/ # Matches 'catatonic' but not 'polecat'
/\Bcat\b/ # Matches 'polecat' but not 'catatonic'
Lựa chọn các giải pháp thay thế
Các | ký tự giống như tiêu chuẩn hoặc bitwise HOẶC trong Perl. Nó chỉ định các đối sánh thay thế trong một biểu thức chính quy hoặc nhóm. Ví dụ: để so khớp "cat" hoặc "dog" trong một biểu thức, bạn có thể sử dụng điều này -
if ($string =~ /cat|dog/)
Bạn có thể nhóm các phần tử riêng lẻ của một biểu thức lại với nhau để hỗ trợ các kết hợp phức tạp. Tìm kiếm tên của hai người có thể đạt được với hai bài kiểm tra riêng biệt, như thế này -
if (($string =~ /Martin Brown/) || ($string =~ /Sharon Brown/))
This could be written as follows
if ($string =~ /(Martin|Sharon) Brown/)
Kết hợp nhóm
Từ quan điểm biểu thức chính quy, không có sự khác biệt giữa ngoại trừ, có lẽ, trước đây rõ ràng hơn một chút.
$string =~ /(\S+)\s+(\S+)/;
and
$string =~ /\S+\s+\S+/;
Tuy nhiên, lợi ích của việc nhóm là nó cho phép chúng ta trích xuất một chuỗi từ một biểu thức chính quy. Các nhóm được trả về dưới dạng danh sách theo thứ tự xuất hiện trong bản gốc. Ví dụ, trong đoạn sau, chúng tôi đã lấy ra giờ, phút và giây từ một chuỗi.
my ($hours, $minutes, $seconds) = ($time =~ m/(\d+):(\d+):(\d+)/);
Cũng như phương pháp trực tiếp này, các nhóm đã so khớp cũng có sẵn trong các biến $ x đặc biệt, trong đó x là số của nhóm trong biểu thức chính quy. Do đó, chúng tôi có thể viết lại ví dụ trước như sau:
#!/usr/bin/perl
$time = "12:05:30";
$time =~ m/(\d+):(\d+):(\d+)/;
my ($hours, $minutes, $seconds) = ($1, $2, $3);
print "Hours : $hours, Minutes: $minutes, Second: $seconds\n";
Khi chương trình trên được thực thi, nó tạo ra kết quả sau:
Hours : 12, Minutes: 05, Second: 30
Khi các nhóm được sử dụng trong biểu thức thay thế, cú pháp $ x có thể được sử dụng trong văn bản thay thế. Do đó, chúng ta có thể định dạng lại chuỗi ngày bằng cách sử dụng:
#!/usr/bin/perl
$date = '03/26/1999';
$date =~ s#(\d+)/(\d+)/(\d+)#$3/$1/$2#;
print "$date\n";
Khi chương trình trên được thực thi, nó tạo ra kết quả sau:
1999/03/26
Khẳng định \ G
Xác nhận \ G cho phép bạn tiếp tục tìm kiếm từ thời điểm trận đấu cuối cùng xảy ra. Ví dụ: trong đoạn mã sau, chúng tôi đã sử dụng \ G để chúng tôi có thể tìm kiếm đến vị trí chính xác và sau đó trích xuất một số thông tin mà không cần phải tạo một biểu thức chính quy phức tạp hơn -
#!/usr/bin/perl
$string = "The time is: 12:31:02 on 4/12/00";
$string =~ /:\s+/g;
($time) = ($string =~ /\G(\d+:\d+:\d+)/);
$string =~ /.+\s+/g;
($date) = ($string =~ m{\G(\d+/\d+/\d+)});
print "Time: $time, Date: $date\n";
Khi chương trình trên được thực thi, nó tạo ra kết quả sau:
Time: 12:31:02, Date: 4/12/00
Khẳng định \ G thực chất chỉ là metasymbol tương đương của hàm pos, vì vậy giữa các lệnh gọi biểu thức chính quy, bạn có thể tiếp tục sử dụng pos, và thậm chí sửa đổi giá trị của pos (và do đó là \ G) bằng cách sử dụng pos làm chương trình con lvalue.
Ví dụ về biểu thức chính quy
Nhân vật văn học
Sr.No. | Ví dụ & Mô tả |
---|---|
1 | Perl Khớp "Perl". |
Các lớp nhân vật
Sr.No. | Ví dụ & Mô tả |
---|---|
1 | [Pp]ython Đối sánh với "Python" hoặc "python" |
2 | rub[ye] Đối sánh với "ruby" hoặc "rube" |
3 | [aeiou] Khớp với bất kỳ một nguyên âm chữ thường nào |
4 | [0-9] Khớp với bất kỳ chữ số nào; giống với [0123456789] |
5 | [a-z] Khớp với mọi ký tự ASCII viết thường |
6 | [A-Z] Khớp với bất kỳ ký tự ASCII viết hoa nào |
7 | [a-zA-Z0-9] Phù hợp với bất kỳ điều nào ở trên |
số 8 | [^aeiou] Khớp với bất kỳ thứ gì khác ngoài một nguyên âm viết thường |
9 | [^0-9] Khớp với bất kỳ thứ gì khác ngoài một chữ số |
Các lớp nhân vật đặc biệt
Sr.No. | Ví dụ & Mô tả |
---|---|
1 | . Khớp với bất kỳ ký tự nào ngoại trừ dòng mới |
2 | \d Khớp một chữ số: [0-9] |
3 | \D Đối sánh với một nondigit: [^ 0-9] |
4 | \s Khớp với một ký tự khoảng trắng: [\ t \ r \ n \ f] |
5 | \S Khớp với khoảng trắng: [^ \ t \ r \ n \ f] |
6 | \w Khớp một ký tự từ duy nhất: [A-Za-z0-9_] |
7 | \W Khớp một ký tự không phải là từ khóa: [^ A-Za-z0-9_] |
Các trường hợp lặp lại
Sr.No. | Ví dụ & Mô tả |
---|---|
1 | ruby? Đối sánh với "rub" hoặc "ruby": y là tùy chọn |
2 | ruby* Đối sánh "chà" cộng với 0 hoặc nhiều y |
3 | ruby+ Đối sánh "chà" cộng với 1 hoặc nhiều y |
4 | \d{3} Khớp chính xác 3 chữ số |
5 | \d{3,} Khớp với 3 chữ số trở lên |
6. | \d{3,5} Đối sánh 3, 4 hoặc 5 chữ số |
Sự lặp lại nông dân
Điều này phù hợp với số lần lặp lại nhỏ nhất -
Sr.No. | Ví dụ & Mô tả |
---|---|
1 | <.*> Lặp lại tham lam: khớp với "<python> perl>" |
2 | <.*?> Nongreedy: đối sánh "<python>" trong "<python> perl>" |
Phân nhóm bằng dấu ngoặc đơn
Sr.No. | Ví dụ & Mô tả |
---|---|
1 | \D\d+ Không có nhóm: + lặp lại \ d |
2 | (\D\d)+ Đã nhóm: + lặp lại cặp \ D \ d |
3 | ([Pp]ython(, )?)+ Khớp "Python", "Python, python, python", v.v. |
Tài liệu tham khảo
Điều này khớp lại với một nhóm đã khớp trước đó -
Sr.No. | Ví dụ & Mô tả |
---|---|
1 | ([Pp])ython&\1ails Khớp với python & pails hoặc Python & Pails |
2 | (['"])[^\1]*\1 Chuỗi được trích dẫn đơn hoặc kép. \ 1 đối sánh với bất kỳ thứ gì mà nhóm đầu tiên phù hợp. \ 2 đối sánh với bất kỳ thứ gì mà nhóm thứ 2 phù hợp, v.v. |
Giải pháp thay thế
Sr.No. | Ví dụ & Mô tả |
---|---|
1 | python|perl Đối sánh với "python" hoặc "perl" |
2 | rub(y|le)) Đối sánh với "ruby" hoặc "rúp" |
3 | Python(!+|\?) "Python" được theo sau bởi một hoặc nhiều! hay một cái? |
Mỏ neo
Điều này cần phải xác định vị trí khớp.
Sr.No. | Ví dụ & Mô tả |
---|---|
1 | ^Python Đối sánh "Python" ở đầu chuỗi hoặc dòng nội bộ |
2 | Python$ Đối sánh "Python" ở cuối chuỗi hoặc dòng |
3 | \APython Đối sánh với "Python" ở đầu chuỗi |
4 | Python\Z Đối sánh "Python" ở cuối một chuỗi |
5 | \bPython\b Đối sánh "Python" ở ranh giới từ |
6 | \brub\B \ B là ranh giới không có từ khóa: đối sánh "rub" trong "rube" và "ruby" nhưng không đối sánh một mình |
7 | Python(?=!) Đối sánh với "Python", nếu theo sau là dấu chấm than |
số 8 | Python(?!!) Đối sánh với "Python", nếu không có dấu chấm than theo sau |
Cú pháp đặc biệt với dấu ngoặc đơn
Sr.No. | Ví dụ & Mô tả |
---|---|
1 | R(?#comment) Đối sánh với "R". Tất cả phần còn lại là bình luận |
2 | R(?i)uby Không phân biệt chữ hoa chữ thường khi đối sánh "uby" |
3 | R(?i:uby) Giống như trên |
4 | rub(?:y|le)) Chỉ nhóm mà không tạo \ 1 backreference |