Biếu thức chính quy

15 1.6K 5
Biếu thức chính quy

Đang tải... (xem toàn văn)

Tài liệu hạn chế xem trước, để xem đầy đủ mời bạn chọn Tải xuống

Thông tin tài liệu

Biểu thức chính qui Khái niệm về biểu thức chính qui Biểu thức chính qui là một khuôn mẫu - một tiêu bản - để đợc sánh với một xâu. Việc sánh một biểu thức chính qui với một xâu thì hoặc thành công hoặc thất bại. Đôi khi, sự thành công hay thất bại này có thể là tất cả những gì bạn quan tâm tới. Vào lúc khác, bạn sẽ muốn lấy một khuôn mẫu đã sánh đúng và thay thế nó bằng một xâu khác, một phần trong đó có thể phụ thuộc đích xác vào cách thức và nơi chốn mà biểu thức chính qui đợc sánh đúng. Biểu thức chính qui thờng đợc nhiều chơng trình UNIX dùng tới, nh grep, sed, awk, ed, vi, emacs và thậm chí cả nhiều vỏ nữa. mỗi chơng trình đều có một tập các kí tự tiêu bản khác nhau (phần lớn là chờm lên nhau). Perl là một siêu tệp ngữ nghĩa cho tất cả những công cụ này - bất kì biểu thức chính qui nào mà có thể đợc viết trong một trong những công cụ UNIX này thì cũng đều có thể đợc viết trong Perl, nhng không nhất thiết dùng hệt các kí tự đó. Cách dùng đơn giản về biểu thức chính qui Nếu chúng ta tìm tất cả các dòng của một tệp có chứa xâu abc, thì ta có thể dùng chỉ lệnh grep: grep abc sonefile > result Trong trờng hợp này, abc là biểu thức chính qui mà chỉ lệnh grep lấy để kiểm tra cho từng dòng đa vào. Những dòng sán hđúng sẽ đợc chuyển ra lối ra chuẩn (ở đây, kết thúc với tệp result vì việc chuyển hớng của vỏ). Trong Perl, ta có thể nói về xâu abc nh biểu thức chính qui bằng việc bao xâu này trong hai dấu sổ chéo: if (/abc/) { print $_; } Nhng cái gì đợc kiểm tra so với biểu thức chính qui abc trong trờng hợp này? Tại sao, anh bạn cũ của chúng ta, biến $_ lại có mặt ở đây? Khi một biểu thức chính qui đợc bao trong hai dấu sổ chéo (nh trên), thì biến $_ sẽ đợc kiểm tra theo biểu thức chính qui đó. Nếu biểu thức chính qui sánh đúng, thì toán tử sánh sẽ cho lại giá trị đúng. Ngoài ra, nó cho lại giá trị sai. Trong thí dụ này, biến $_ đợc giả sử có chứa một dòng văn bản nào đó, và đợc in ra nếu dòng này có chứa các kí tự abc đâu đó bên trong dòng - tơng tự nh chỉ lệnh grep ở trên. Không giống nh chỉ lệnh grep, vốn vận hành trên tất cả các dòng của tệp, đoạn chơng trình Perl này chỉ nhìn vào có một dòng thôi. Để làm việc trên tất cả các dòng, ta cần thêm vào một chu trình, nh trong: while (<>) { if (/abc/) { print $_; } } Điều gì sẽ xảy ra nêu nh ta không biết đợc số của các b giữa a và c? Tức là, điều gì sẽ xảy ra nếu ta muốn in dòng có chứa một a và theo sau nó là không hay nhiều b, rồi theo sau nữa là một c? Với grep, ta phải nói: grep ab*c somefile > result (Đối này có chứa dấu sao trong ngoặc kép bởi vì chúng ta không muốn lớp vỏ trải rộng đối đó cứ nh là một mẫu tên tệp. Nó phải đợc truyền qua grep để có hiệu quả.) Thế mà trong Perl, chúng ta có thể nói đích xác cùng điều đó: while (<>) { if (/ab*c/) { print $_; } } Cũng hệt nh grep, điều này có nghĩa là một a theo sau bởi không hay nhiều b, theo sau là c. Chúng ta sẽ xem xét nhiều tuỳ chọn khác về toán tử đối sánh trong mục Nói thêm về toán tử đối sánh, ở cuối chơng này, sau khi ta đã nói về tất cả các loại biểu thức chính qui. Một toán tử biểu thức chính qui nữa là toán tử thay thế, làm việc thay thế một phần của xâu mà sánh đúng biểu thức chính qui bằng một xâu khác. Toán tử thay thế giống nh chỉ lệnh s trong sed, bao gồm một chữ s, một sổ chéo, một biểu thức chính qui, một sổ chéo, một xâu thay thế, và một sổ chéo cuối cùng, trông tựa nh thế này: s/ab*c/def/; Xâu (trong trờng hợp này là biến $_) đợc đem ra đối sánh với biểu thức chính qui (ab*c). Nếu việc đối sánh thành công, thì phần của xâu sán hđúng sẽ bị loại ra và đợc thay thế bằng xâu thay thế (def). Nếu việc đối sánh không thành công thì chẳng có gì xảy ra cả. Nh với toán tử đối sánh, ta sẽ còn xem xét lại vô số các tuỳ chọn về toán tử thay thế dới đây, trong mục Thay thế. Khuôn mẫu Một biểu thức chính qui là một khuôn mẫu. Một số phần của khuôn mẫu sánh đúng chỉ các kí tự trong xâu thuộc kiểu đặc biệt. Những phần khác của khuôn mẫu sánh đúng cho đa kí tự, hay đa đa kí tự. Trớc hết, ta sẽ xem các khuôn mẫu một kí tự, rồi đến các khuôn mẫu đa kí tự. Khuôn mẫu một kí tự Kí tự sánh mẫu đơn giản nhất và thông dụng nhất trong các biểu thức chính qui là một kí tự sánh với chính nó. Nói cách khác, đặt một chữ a vào trong biểu thức chính qui đòi hỏi một chữ tơng ứng a trong xâu. Kí tự sánh mẫu thông dụng nhất tiếp đó là dấu chấm Dấu chấm đối sánh bất kì kí tự riêng lẻ nào ngoại trừ dấu dòng mới (\n). Chẳng hạn, khuôn mẫu /a./ đối sánh bất kì dãy hai kí tự nào bắt đầu bằng a và không phải là a\n. Lớp kí tự sánh mẫu đợc biểu diễn bởi cặp dấu ngoặc vuông mở và đóng, và một danh sách các kí tự nằm giữa hai dấu ngoặc này. Một và chỉ một trong các kí tự này phải hiện diện tại phần tơng ứng của xâu cần sánh mẫu. Chẳng hạn, /[abcde]/ sánh với bất kì một trong năm chữ đầu tiên của bảng chữ thờng, trong khi /[aeiouAEIOU]/ lại sánh với bất kì năm nguyên âm hoặc chữ thờng hoặcchữ hoa. Nếu bạn muốn đặt dấu ngoặc vuông phải (]) vào danh sách thì hãy đặt một sổ chéo ngợc ở trớc nó, hay đặt nó nh kí tự đầu tiên bên trong danh sách. Phạm vi của các kí tự (nh a tới z0 có thể đợc viết tắt bằng việc chỉ ra những điểm cuối của phạm vi đợc tách biệt bởi dấu gạch ngang (-); để có đợc hằng kí hiệu gạch ngang, bạn hãy đặt trớc dấu gạch ngang một sổ chéo ngợc. Sau đây là một số thí dụ khác: [0123456789] # sánh với mọi chữ số [0-9] # cũng thế [0-9\-] # sánh 0-9 hay dấu trừ [a-z0-9] # sánh bất kì chữ thờng hay số nào [a-zA-Z0-9_] # sánh bất kì chữ, số hay dấu gạch thấp Cũng có lớp kí tự bị phủ định, cũng là cùng lớp kí tự, nhng có thêm dấu mũi tên ngợc (hay dấu mũ ^) đằng trớc, đi ngay sau dấu ngoặc trái. Lớp kí tự này đối sánh với bất kì kí tự đơn nào không trong danh sách. Chẳng hạn: [^0-9] # sánh với bất kì kí tự phi số nào [^aeiouyAEIOUY] # sánh với bất kì kí tự nào không nguyên âm [^\^] # sánh với một kí tự đơn trừ mũi tên ngợc Để tiện cho bạn, đã có định nghĩa sẵn một số lớp ksi tự chung, nh đợc mô tả trong Bảng 7-1. Bảng 7-1: Viết tắt cho lớp kí tự định sẵn Kết cấu Lớp tơng đơng Kết cấu phủ định Lớp phủ định tơng đ- ơng \d (số) [0-9] \D (số, không!) [^0-9] \w (từ) [a-zA-Z0- 9_] \W (từ, không!) [^a-zA-Z0- 9_] \s (cách) [ \r\t\n\f] \S (cách, không!) [^ \r\t\n\f] Khuôn mẫu \d sánh với số. Khuôn mẫu \w sánh với kí tự từ, mặc dầu điều thực sự sánh đúng là bất kì cái gì hợp lệ trong tên biến Perl. Khuôn mẫu \s sánh với dấu cách (khoảng trắng), ở đây đợc xác định nh dấu cách, về đầu dòng (không hay dùng mấy trong UNIX), tab, xuống dòng (dấu dòng mới của UNIX), và kéo giấy. Các bản chữ hoa sánh đúng với cái đối lập cho những lớp này. Khuôn mẫu nhóm Sức mạnh thực sự của biểu thức chính qui là khi bạn có thể nói một hay nhiều những thứ này hay cho tới năm thứ này. Ta hãy nói về cách thực hiện điều này. Dãy Khuôn mẫu nhóm đầu tiên (và có lẽ kém hiển nhiên nhất) là dãy. Điều này có nghĩa là abc sánh đúng với một a theo sau là b, theo sau là c. Nó dờng nh đơn giản, nhng tôi cứ đặt tên cho nó để tôi có thể nói về nó sau này. Bội Chúng ta đã thấy dấu sao (*) nh một khuôn mẫu nhóm. Dấu sao chỉ ra rằng không hay nhiều kí tự (hay lớp kí tự) đứng ngay trớc nó. Hai khuôn mẫu nhóm khác làm việc giống thế là dấu cộng (+), nghĩa là một hay nhiều kí tự đứng nagy trớc, và dấu hỏi (?), nghĩa là không hay một kí tự ngay trớc. Chẳng hạn, biểu thức chính qui /fo+ba?r/ sánh đúng cho một f theo sau là một hay nhiều o, theo sau là a, b và tuỳ chọn a, theo sau là một r. Trong tất cả ba khuôn mẫu nhóm này, các khuôn mẫu đều tham lam. Nếu một khuôn mẫu nh vậy có cơ hội sánh đúng giữa năm và mời kí tự thì nó sẽ lọc ra xâu mời kí tự mỗi lúc. Chẳng hạn: $_ = fred xxxxxxxxxx barney; s/x*/boom/; bao giờ cũng thay tất cả các x liên tiếp bằng boom (kết quả là fred boom barney), thay vì chỉ thay thế cho một hay hai x, cho dù một tập x ngắn hơn cũng sánh đợc cho cùng biểu thức chính qui Nếu bạn cần nói năm tới mời x, thì bạn có thể xoay xở bằng cách đặt năm x theo sau bởi năm x nữa đi liền sau dấu chấm hỏi. Nhng làm thế trông xấu, mà cũng chẳng làm việc tốt lắm. Thay vì vậy, có một cách dễ hơn: số bội tổng quát. Số bội tổng quát bao gồm một cặp dấu ngoặc nhọn với một hay hai số bên trong, nh trong /x{5,10}/. Giống nh ba số bội khác, kí tự đứng ngay trớc (trong trờng hợp này là chữ x) phải đợc tìm thấy bên trong số lần lặp đã chỉ ra (năm đến mời ở đây). Nếu bạn bỏ đi con số thứ hai, nh trong /x{5,}/, thì điều này có nghĩa là nhiều hay hơn nữa (năm hay nhiều hơn trong trờng hợp này), và nếu bạn bỏ nốt dấu phẩy, nh trong /x{5}/, thì điều đó có nghĩa là đúng con số này (năm x). Để đợc 5 x hay ít hơn, bạn phải đặt số không vào, nh trong /x{0,5}/. Vậy, biểu thức chính qui /a.{5}b/ sánh đúng cho kí tự a đợc tách với ksi tự b bởi bất kì năm kí tự khác kí tự dòng mới. (Nhớ lại rằng dấu chấm sánh với bất kì kí tự khác dấu dòng mới, và chúng ta sánh với năm kí tự nh thế ở đây.) Năm kí tự này không cần phải nh nhau. (Chúng ta sẽ biết cách để buộc chúng là nh nhau trong mục tiếp.) Ta có thể miễn trừ hoàn toàn bằng *, +, và ?, vì chúng hoàn toàn tơng đơng với {0,}, {1,}, và {0,1}. Nhng dễ dàng hơn vẫn là gõ một kí tự ngắt tơng đơng, mà cũng quen thuộc hơn. Nếu có hai số bội trong một biểu thức, thì qui tắc tham lam đợc tăng lên với bên trái nhất là tham nhất. Chẳng hạn: $_ = a xxx c xxxxxxx d; /a.*c.*d/; Trong trờng hợp này, .* thứ nhất trong biểu thức chính qui sánh với tất cả các kí tự cho tới c thứ hai, cho dù việc sánh đúng chỉ với các kí tự cho tới c đầu tiên vẫn cho phép toàn bộ biểu thức chính qui đợc sánh. Điều này không tạo ra khác biệt gì (khuôn mẫu sẽ sánh theo cả hai cách), nhng sau này khi chúng ta có thể nhìn vào các bộ phận của biểu thức chính qui mà đợc sánh, thì sẽ có đôi chút vấn đề. Điều gì xảy ra nếu biểu thức xâu và chính qui hơi bị thay đổi đi, chẳng hạn nh: $_ = a xxx ce xxxxxxx ci xxx d; /a.*ce.*d/; Trong trờng hợp này, nếu .* sánh với phần lớn các kí tự có thể trớc c tiếp, thì kí tự biểu thức chính qui tiếp (e) sẽ không sánh với kí tự tiếp của xâu (i). Trong trờng hợp này, ta thu đợc việc lần ngợc tự động - số bội bị tháo ra và thử lại, dừng lại tại chỗ nào đó phía trớc (trong trờng hợp này, tại c trớc, tiếp sau là (e) * . Một biểu thức chính * * Về mặt kĩ thuật, có nhiều cách lần ngợc của toán tử * để tìm ra c ở vị trí đầu tiên. Nhng phải hơi thủ thuật hơn để mô tả nó, mà nó vẫn hoạt động theo cùng nguyên lí. qui phức tạp có thể bao gồm nhiều mức lần ngợc nh vậy, dẫn tới thời gian thực hiện lâu. Dấu ngoặc tròn nh bộ nhớ Một toán tử nhóm khác là cặp mở và đóng ngoặc tròn quanh bất kì phần khuôn mẫu nào. Điều này không làm thay đổi liệu khuôn mẫu có sánh đúng hay không, nh- ng thay vì thế lại làm cho một phần của xâu đợc khuôn mẫu sánh đúng sẽ đợc ghi nhớ, để cho nó có thể đợc tham khảo tới về sau. Vậy chẳng hạn, (a) vẫn sánh với a, còn ([a-z]) thì vẫn sánh với bất kì chữ thờng nào. Để nhớ lại một phần đã ghi nhớ của một xâu, bạn phải đa vào một dáu sổ chéo ngợc theo sau bởi một số nguyên. Kết cấu khuôn mẫu này biểu thị cho cùng dãy các kí tự đợc sánh trớc đây trong cặp dấu ngoặc tròn cùng số (đếm từ một) . Chẳng hạn: /fred(.)barney\1/; sánh một xâu có chứa fred, tiếp theo là một kí khác dấu dòng mới, tiếp nữa là barney, rồi tiếp bởi cùng một kí tự đó. Vậy, nó sánh với fredxbarneyx, nhng không sánh với fredxbarneyy. Bạn hãy so sánh điều đó với: /fred.barney./ trong đó hai kí tự không xác định có thể là một, hay khác nhau - cũng chẳng thành vấn đề gì. Số 1 đến từ đâu vậy? Nó có nghĩa là phần biểu thức chính qui nằm trong dấu ngoặc đầu tiên. Nếu có nhiều phần nh thế, thì phần thứ hai (đếm các dấu ngặc trái từ trái sang phải) sẽ đợc tham khảo tới là \2, phần thứ ba là \3, và cứ thế. Chẳng hạn: /a(.)b(.)c\2d\1/; sẽ sánh với một a, một kí tự (gọi nó là #1), một b, một kí tự khác (gọi nó là #2), một c, kí tự #2, một d, và kí tự #1. Cho nên nó sánh với axbycydx, chẳng hạn. Phần đợc tham khảo tới có thể nhiều hơn một kí tự. Chẳng hạn: /a(.*)b\1c/; sánh với một a, theo sau bởi một số bất kì kí tự nào (thậm chí không), theo sau bởi b, theo sau bởi cùng dãy kí tự đó, theo sau bởi c. Vậy, nó sẽ sánh với aFREDnFREDc, hay thậm chí abc, nhng không aXXbXXXc. Một cách dùng khác của phần đợc nhớ của biểu thức chính qui là trong xâu thay thế của chỉ lệnh thay thế. Kết cấu kiểu \1 vẫn giữ giá trị của chúng trong xâu thay thế, và có thể đợc tham khảo tới để xây dựng xâu, nh trong: $_ = a xxx b yyy c zzz d; s/b(.*)c/d\1e/; mà sẽ thay thế b và c bằng d và e, vẫn giữ lại phần ở giữa. Thay phiên Một kết cấu nhóm khác là thay phiên, nh trong a|b|c. Điều này có nghĩa là sánh đúng một trong các khả năng (a hay b hay c trong trờng hợp này). Điều này vẫn có tác dụng ngay cả khi các thay phiên có nhiều kí tự, nh trong /song|blue/, sẽ sánh hoặc song hoặc blue. (Với những thay phiên đơn giản, tốt hơn cả là bạn có thể bỏ lớp kí tự nh /[abc]/.) Điều gì xảy ra nếu ta muốn sánh songbird hay bluebird? Ta có thể viết /songbird| bluebird/, nhng phần bird đó không nên có đó hai lần. Trong thực tế, cũng có cách ra, nhng ta phải nói tới thứ tự u tiên cho các khuôn mẫu nhóm, sẽ đợc đề cập tới trong mục Thứ tự u tiên dới đây. Khuôn mẫu neo Bốn kí pháp đặc biệt đóng neo cho một khuôn mẫu. Thông thờng, khi một khuôn mẫu đợc sánh với xâu thì sự bắt đầu của khuôn mẫu đó đợc rê đi trong toàn bộ xâu từ trái sang phải, sánh với cơ hội có thể đầu tiên. Neo cũng cho phép bạn đảm bảo rằng các phần của dòng khuôn mẫu sắp thẳng với những phần đặc biệt của xâu. Cặp neo thứ nhất đòi hỏi rằng một phần đặc biệt của việc đối sánh phải đợc định vị tại biên giới từ hay không tại biên giới từ. Neo \b yêu cầu một biên giới từ tại điểm đã chỉ ra cho khuôn mẫu đối sánh. Biên giới từ là nơi ở giữa các kí tự sánh với \w và \W, hay giữa các kí tự sánh với \w và chỗ bắt đầu hay kết thúc của xâu. Chú ý rằng điều này ít phải xử lí đối với tiếng Anh và phải làm nhiều đối với các kí hiệu C, nhng điều đó cũng gần thôi khi ta đạt tới. Chẳng hạn: /fred\b/; # sánh fred, nhng không Frederick /\bwiz/; # sánh wiz và wizard, nhng không qwiz /\bFred\b/; # sánh Fred nhng không Frederick hay alFred /abc\bdef/; # không bao giờ sánh (không thể có cận ở đây) Giống thế, \B yêu cầu không có biên giới từ tại vị trí đã chỉ ra. Chẳng hạn: /\bFred\B/; # sánh Frederick nhng không Fred Flintstonee Hai neo nữa yêu cầu rằng một phần đặc biệt của khuôn mẫu phải đi ngay sau cuối xâu. Dấu mũ (^) sánh với điểm bắt đầu của xâu nếu nó đang ở một vị trí tạo ra nghĩa để đối sánh tại chỗ bắt đầu của xâu. Chẳng hạn, ^a sánh một a nếu và chỉ nếu a là kí tự đầu tiên của xâu. Tuy nhiên, ^a cũng sánh với hai kí tự a và ^ ở bất kì đâu trong xâu. Nói cách khác, dấu mũ đã mất ý nghĩa đặc biệt của nó. Nếu bạn cần dấu mũ là một hằng kí hiệu dấu mũ ngay tại chỗ bắt đầu, thì hãy đặt một dấu sổ chéo ngợc phía trớc nó. Dấu $ cũng giống nh ^, neo lại khuôn mẫu, nhng tại cuối của xâu, không phải bắt đầu. nói cách khác, c$ sánh với một c chỉ nếu nó xuất hiện tại cuối xâu. Dấu đô la ở bất kì nơi đâu khác trong khuôn mẫu có lẽ vẫn cứ đợc diễn giải nh cách hiểu giá trị vô hớng, cho nên bạn gần nh bao giờ cũng phải dùng dấu sổ chéo ngợc để đối sánh một dấu hiệu đô là hàng kí hiệu trong xâu. Thứ tự u tiên Vậy điều gì xảy ra khi ta lấy a|b* cùng nhau? Liệu đây là a hay b một số lần bất kì hay chỉ một a hay nhiều b? Đợc rồi, cũng giống nh các toán tử có số u tiên, các khuôn mẫu bỏ neo và gộp nhóm cũng có số u tiên. Số u tiên của khuôn mẫu từ cao xuống thấp nhất đợc cho trong Bảng 7-2. Bảng 7-2: Số u tiên toán tử gộp nhóm biểu thức chính qui (cao nhất xuống thấp nhất) Tên Biểu diễn Dấu ngoặc tròn ( ) Số bội + * ? {m,n} Tuần tự và bỏ neo abc^$\b\B Thay phiên | Theo bảng này, * có số u tiên cao hơn |. Cho nên /a|b*/ đợc diến giải nh một a, hay số bất kì b. Điều gì xảy ra nếu ta muốn một nghĩa khác, nh trong bất kì số a hay b nào? Chúng ta đơn thuần chỉ ném vào một cặp dấu ngoặc. Trong trờng hợp này, bạn hãy bao phần của biểu thức mà toán tử * cần áp dụng, vào bên trong các dấu ngoặc, và ta sẽ đợc nó, nh (a|b)*. Nếu bạn muốn làm rõ ràng biểu thức thứ nhất, thì bạn có thể đóng dấu ngoặc d thừa nó với a|(b*). Khi bạn dùng dấu ngoặc để tác động tới số u tiên thì chúng cũng đặt lẫy bộ nhớ, nh đã chỉ ra trớc đây trong chơng này. Tức là tập các dấu ngoặc này sẽ cần đợc đếm khi bạn muốn nói tới một cái gì đó là \2, \3 hay bất kì cái gì. Một ngày nào đó có thể có một loại dấu ngoặc mà không phải đếm, nhng cha có trong lần đa ra Perl 4.036. Sau đây là một số thí dụ khác về biểu thức chính qui, và tác động của dấu ngoặc: abc* $ sánh với ab, abc, abcc, abccc, abcccc vân vân (abc)* # sánh với , abc, abcabc, abcabcabc vân vân ^x|y # sánh x tại đầu dòng, hay y ở bất kì đâu ^(x|y) # sánh hoặc với x hoặc với y tại đầu dòng a|bc|d # a hoặc bc hoặc d (a|b)(c|d) # ac, ad, bc hoặc bd (song|blue)bird # songbird hay bluebird Thêm về toán tử đối sánh Ta đã nhìn vào cách dùng đơn giản nhất của toán tử đối sánh (một biểu thức chính qui đợc bao trong sổ chéo). Bây giờ ta hãy nhìn vào vô vàn cách làm cho toán tử này làm đợc điều gì đó hơi khác hơn. Chọn một mục tiêu khác (toán tử =~) Đôi khi xâu bạn muốn sánh với khuôn mẫu lại không bên trong biến $_, và đó sẽ là sắc thái để đặt nó ở đó (có lẽ bạn đã có một giá trị trong $_ mà bạn rất thích). Không hề gì. Toán tử =~ sẽ giúp chúng ta ở đây. Toán tử này nhận một toán tử biểu thức chính qui ở vế bên phải, rồi thay đổi đối tợng của toán tử này thành một cái gì đó bên cạnh biến $_ - có nghĩa là một giá trị nào đó có tên bên vế trái của toán tử này. Nó trông tựa nh thế này: $a = hello world; $a =~ /^he/; # đúng $a =~ /(.)\l/; # cũng đúng (sánh với hai l) if ($a =~ /(.)\1/) { # đúng, cho nên có . # một số chất liệu khác } Mục tiêu của toán tử =~ có thể là bất kì biểu thức nào cho một giá trị xâu vô hớng nào đó. Chẳng hạn, <STDIN> cho một giá trị xâu vô hớng khi đợc dùng trong hoàn cảnh vô hớng, cho nên chúng ta có thể tổ hợp điều này với toán tử =~ và một toán tử sánh biểu thức chính qui để đợc một kiểm tra gọn gàng về cái vào đặc biệt, nh trong: print còn yêu cầu nào nữa không?; if (<STDIN> =~ /^[yY]/) { # cái vào có bắt đầu bằng một y không? print Vậy yêu cầu đó có thể là gì? ; <STDIN>; # bỏ một dòng cái vào chuẩn print Rất tiếc, tôi không thể làm đợc điều đó.\n; Trong trờng hợp này, toán tử <STDIN> cho dòng tiếp từ cái vào chuẩn, mà rồi ngay lập tức đợc dùng nh xâu đem sánh với khuôn mẫu ^[yY]. Lu ý rằng bạn cha bao giờ cất giữ cái vào vào một biến, cho nên nếu bạn muốn sánh cái vào với mẫu khác, hay có thể cho hiện lại dữ liệu trong một thông báo lỗi thì bạn khong gặp may rồi. Nhng dạng này thờng hay đến đúng lúc. Bỏ qua chữ hoa thờng Trong thí dụ trớc, tôi đã dùng [yY] để đối sánh hoặc chữ Y hoa hoặc y thờng. Với những xâu rất ngắn nh y hay fred thì điều này là dễ dàng, nh [fF] [oO][oO]. Nhng điều gì xẩy ra nếu xâu tôi muốn sánh lại là từ procedure trong hoặc chữ thờng hoặc chữ hoa? Trong một số bản của grep, cờ -i chỉ ra bỏ qua hoa thờng. Perl cũng có tuỳ chọn nh vậy. Bạn chỉ ra tuỳ chọn bỏ qua hoa thờng bằng cách thêm vào chữ i thờng vào sau sổ chéo đóng, nh trong /somepattern/i. Điều này nói lên rằng các chữ của khuôn mẫu này sẽ sánh với các chữ trong xâu trong cả chữ hoa lẫn thờng. Chẳng hạn, để sánh từ procedure trong cả hoa lẫn thờng tại đầu dòng, bạn hãy dùng /^procedure/i. Bây giờ thí dụ trớc của ta trong giống thế này: print còn yêu cầu nào nữa không?; if (<STDIN> =~ /^y/i) { # cái vào có bắt đầu bằng một y không? # có! xử lí cho nó . } Dùng một định biên khác Nếu bạn đang tìm kiếm một xâu với một biểu thức chính qui có chứa kí tự sổ chéo (/), thì bạn phải đặt trớc mỗi sổ chéo một sổ chéo ngợc (\). Chẳng hạn, bạn có thể tìm một xâu bắt đầu bằng /usr/etc tựa nh thế này: $path = <STDIN>; # đọc một tên đờng dẫn (có lẽ từ find?) if ($path =~ /^\/usr\/etc/) { # bắt đầu với /usr/etc . } Nh bạn có thể thấy, tổ hợp sổ chéo ngợc-sổ chéo làm cho nó trông giống nh có một thung lũng nhỏ giữa hai mẩu văn bản. Làm điều này cho nhiều sổ chéo có thể gây cồng kềnh, cho nên Perl cho phép bạn xác định một kí tự định biên khác. Chỉ cần đặt trớc bất kì kí tự phi chữ-số * nào (định biên do bạn chọn) với một m, rồi liệt kê khuôn mẫu của bạn theo sau bởi một kí tự định biên y hệt thế nữa, là bạn đã hoàn thành, nh trong: /^\/usr/etc/ # dùng định biên sổ chéo chuẩn m@^/usr/etc@ # dùng @ làm định biên m#^/usr/etc# # dùng # làm định biên (sở thích của tôi) Bạn có thể thậm chí dùng cả sổ chéo lần nữa nếu bạn cứ muốn, nh trong m/fred/, cho nên toán tử sánh biểu thức chính qui thông thờng thực sự là toán tử m, tuy nhiên, m là tuỳ chọn, nếu bạn chọn sổ chéo làm định biên. Dùng xen lẫn biến Một biểu thức chính qui là đợc xen lẫn biến trớc khi nó đợc xem xét cho các kí tự đặc biệt khác. Do đó, bạn có thể xây dựng một biểu thức chính qui từ các xâu đwojc tính toán thay vì chỉ là hằng ksi hiệu. Chẳng hạn: $what = bird; $sentence = Mọi con chim tốt đều bay.; if ($sentence =~ /\b$what\b/) { print Câu này chứa từ $what!\n; * * Nếu dấu định biên ngẫu nhiên là kí tự bên trái hay cặp trái-phải (ngoặc tròn, ngoặc nhọn hay ngoặc vuông), thì dấu định biên đóng là kí tự bên phải của cùng cặp đó. Nhng ngoài ra, các kí tự là hệt nhau cho bắt đầu và kết thúc. [...]... join() Biểu thức chính qui có thể đợc dùng để chặt một xâu thành các trờng Toán tử split() thực hiện điều này còn toán tử join() lại có thể dính các mẩu lại với nhau Toán tử split() Toán tử split() nhận một biểu thức chính qui và một xâu rồi tìm tất cả mọi sự xuất hiện của biểu thứcchính qui bên trong xâu này (dờng nh bạn đã thực hiện toán tử s///g) Các bộ phận của xâu không sánh với biểu thức chsinh... bằng goodbye Các kí tự khuôn mẫu trong biểu thức chính qui cho phép các khuôn mẫu đợc đối sánh, thay vì chỉ là các kí tự cố định: $_ = đây là phép kiểm tra; s/(\w+)//g; # $_ bây giờ là Nhớ lại rằng $1 đợc đặt là dữ liệu bên trong việc đối sánh đúng mẫu trong dấu ngoặc Hậu tố i (hoặc trớc hoặc sau g nếu có) làm cho biểu thức chính qui trong toán tử thay thế bỏ qua chữ... ghi nhớ, nhng chỉ nếu biểu thức chính qui sánh đúng Ta hãy lấy lại thí dụ trớc theo cách khác $_ = đây là phép kiểm tra; ($first, $second) = /(\W+)\W+(\W+)/; # đối sánh hai từ đầu # $first bây giờ là đây còn $second bây giờ là là Lu ý rằng các biến $1 và $2 vẫn không bị thay đổi Các biến chỉ đọc đợc xác định trớc còn bao gồm $&, mà là một phần của xâu sánh đúng với biểu thức chính qui; $`, là một phần... Chẳng hạn, để xây dựng lại dòng mật hiệu, bạn hãy thử một cách kiểu nh: $outline = join(:, @fields); Lu ý rằng xâu gắn không phải là biểu thức chính qui - chỉ là một xâu bình thờng gồm không hay nhiều kí tự Bài tập Xem Phụ lục A về lời giải 1 Hãy xây dựng một biểu thức chính qui mà sánh cho: (a) ít nhất một a theo sau bởi một số bất kì b (b) một số bất kì dấu sổ chéo ngợc theo sau bởi một số bất kì dấu... vào scream nó sẽ không tìm thấy Nếu bạn đa vào [bw]ird, điều ấy cũng đợc tìm ra, chỉ ra rằng các kí tự đối sánh khuôn mẫu biểu thức chính qui quả thực là vẫn có ý nghĩa Tôi sẽ chỉ ra cho bạn trong phần Thay thế dới đây về cách thay đổi xâu để cho các ksi tự đối sánh khuôn mẫu chính qui đợc tắt đi Biến chỉ đọc đặc biệt Sau khi đối sánh khuôn mẫu thành công, các biến $1, $2, $3 vân vân sẽ đợc đặt cho cùng...} Tại đây chúng ta đã xây dựng một cách có hiệu quả toán tử biểu thức chính qui /\bbird\b/ bằng việc dùng một tham khảo biến Sau đây là một thí dụ có hơi phức tạp hơn: $sentence = Mọi con chim tốt đều bay.; print Tôi phải tìm cái gì đây?; $what = ; chop ($what) . Biểu thức chính qui Khái niệm về biểu thức chính qui Biểu thức chính qui là một khuôn mẫu - một tiêu bản - để đợc sánh với một xâu. Việc sánh một biểu thức. Khi một biểu thức chính qui đợc bao trong hai dấu sổ chéo (nh trên), thì biến $_ sẽ đợc kiểm tra theo biểu thức chính qui đó. Nếu biểu thức chính qui sánh

Ngày đăng: 28/09/2013, 10:20

Từ khóa liên quan

Tài liệu cùng người dùng

Tài liệu liên quan