intTypePromotion=1
zunia.vn Tuyển sinh 2024 dành cho Gen-Z zunia.vn zunia.vn
ADSENSE

Learning Perl - Biểu thức chính qui part 2

Chia sẻ: AJFGASKJHF SJHDB | Ngày: | Loại File: PDF | Số trang:5

90
lượt xem
6
download
 
  Download Vui lòng tải xuống để xem tài liệu đầy đủ

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ư đã c hỉ ra trước đây trong c hươ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ì. Nếu bạn muốn dùng dấu ngoặc trong trường hợp này nhưng không muốn lưu lại trong bộ nhớ...

Chủ đề:
Lưu

Nội dung Text: Learning Perl - Biểu thức chính qui part 2

  1. c ần áp dụng, vào bên trong các dấu ngoặc , và t a 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ư đã c hỉ ra trước đây trong c hươ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ì. Nếu bạn muốn dùng dấu ngoặc trong trường hợp này nhưng không muốn lưu lại trong bộ nhớ (dạng \1 \2 \3) bạn hãy dùng (?: ) t hay c ho ( ). Sau đây là một số thí dụ khác về biểu thức c hính qui, và tác động c ủa dấu ngoặc: s ánh với ab, abc, abc c, abc c c, abc cc c vân vân # abc* s ánh với "", abc, abc abc , abcabcabc vân vân # (abc)* 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 # ^(x|y) a hoặc bc hoặc d # a|bc|d ac , ad, bc hoặc bd # (a|b)(c|d) s ongbird hay bluebird # (song|blue)bird 7.4 Thêm về toán tử đối sánh Ta đã nhìn vào c ác h 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 t rong sổ c héo). Bây giờ ta hãy nhìn vào vô vàn c ác h làm cho toán tử này làm được điều gì đó hơi khác hơn. 7.4.1 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íc h và không muốn t hay đổi nó). Không hề gì. Toán tử =~ sẽ giúp c húng t a ở đây. Toán tử này nhận một toán tử biểu thức c hính qui ở vế bên phải, rồi t hay đổ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 t oán tử này. Nó trông tựa như thế này: $a = "hello world"; $a =~ /^he/; $a =~ /(.)\l/; if ($a =~ /(.)\1/) { ... } 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, c ho một giá trị xâu vô hướng khi được dùng t rong hoàn c ảnh vô hướng, cho nên c hú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 "any more?"; if ( =~ /^[yY]/) { # c ó phải bắt đầu bằng một c hữ y không? print "So what is it? "; ; # bỏ qua 1 dòng print "Sorry, I'm unable to do that.\n"; } Trong trường hợp này, toán tử đọc 1 dòng từ lồi vào chuẩn (bàn phím), mà rồi ngay lập tức được dùng như xâu đem sánh với khuôn mẫu ^ [yY]. Lưu ý rằng bạn c hưa bao giờ c ất giữ cái vào vào một biến, c ho nên nếu bạn muốn sánh c ái vào với mẫu khác , hay c ó t hể c ho 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. Nhưng dạng này thường hay đến đúng lúc . 7.4.2 Bỏ qua chữ hoa thường Trong thí dụ trước , tôi đã dùng [yY] để đối sánh hoặc c hữ Y hoa hoặc y thường. Với những xâu rất ngắn như y hay jerry thì điều này là dễ dàng, như [fF] [oO] [oO]. Nhưng điều gì xẩy ra nếu xâu tôi muốn sánh lại là từ "procedure" trong hoặc c hữ thường hoặc c hữ hoa?
  2. T rong một số phiên bản c ủa grep, c ờ - i c hỉ ra "bỏ qua hoa thường". Perl c ũng c ó tuỳ c họn như vậy. Bạn c hỉ ra tuỳ chọn bỏ qua hoa t hường bằng các h thêm vào c hữ i t hường vào sau sổ c héo đóng, như trong /somepattern/i. Điều này nói lên rằng c ác c hữ c ủa khuôn mẫu này sẽ sánh với c ác c hữ trong xâu trong c ả c hữ hoa lẫn thường. Chẳng hạn, để sánh từ "proc edure" 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 "anu more?"; if ( =~ /^y/i) { # c ó! xử lí c ho nó ... } 7.4.3 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 ó c hứa kí tự sổ c héo (/), thì bạn phải đặt trước mỗi sổ c héo một sổ c hé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 = ; # đọc một tên đường dẫn if ($path =~ /^\/usr\/etc/) { # bắt đầu với /usr/etc ... } Như bạn c ó thể thấy, tổ hợp sổ c héo ngược -sổ c héo làm c ho 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 ó t hể gây c ồng kềnh, c ho 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 c họ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ổ c héo c huẩ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 c hí dùng c ả sổ c héo lần nữa nếu bạn c ứ muốn, như trong m/jerry/, c ho nên toán tử sánh biểu thức chính qui thông t hường thực sự là toán tử m, tuy nhiên, m là tuỳ chọn, nếu bạn c họn sổ c héo làm định biên. 7.4.4 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 c ho c ác kí tự đặc biệt khác . Do đó, bạn có thể xây dựng một biểu thức c hính qui từ c ác xâu được tính toán thay vì chỉ là hằng ký hiệu. Chẳng hạn: $what = "bird"; $sentence = "Every good bird does fly."; if ($sentence =~ /\b$what\b/) { print "$sentence\n"; } Tại đây c húng ta đã xây dựng một c ác h c ó hiệu quả toán tử biểu thức c hí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 = "Every good bird does fly."; print "What should I find? "; $what = ; chop ($what); if ($sentence =~ /$what/) { # tìm thấy nó! print "Yes, saw $what in $sentence.\n"; } else {
  3. print "No...nothing!.\n"; } Nếu bạn đưa vào bird, thì nó được tìm ra. Nếu bạn đưa vào s cream 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, c hỉ ra rằng các kí t ự đối sánh khuôn mẫu biểu thức c hí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 ác h thay đổi xâu để cho các ký tự đối sánh khuôn mẫu chính qui được tắt đi. 7.4.5 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 c ho c ùng giá trị là \1, \2, \3 t ương ứng. Bạn có thể dùng điều này để nhìn vào một phần c ủa việc đối sánh trong đoạn chương trình sau. Chẳng hạn: $_ = “đây là phép kiểm tra”; /(\W+)\W+(\W+)/; # đối sánh hai từ đầu # $1 bây giờ là “đây” c òn $2 bây giờ là “là” Bạn c ũng c ó thể thu được c ùng c ác giá trị ($1, $2, $3 v ân vân) bằng việc đặt đối sánh trong hoàn cảnh mảng. Kết quả là một danh sác h c ác giá trị mà sẽ được đặt c ho $1 c ho tới số c ác vật được ghi nhớ, nhưng chỉ nếu biểu thức c hính qui sánh đúng. Ta hãy lấy lại thí dụ trước theo c ác h khác $_ = "This is a test"; /(\W+)\W+(\W+)/; # đối sánh hai từ ở hai đầu # $1 bây giờ là "this" c òn $2 bây giờ là "test" Lưu ý 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 $&, 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 c ủa xâu trước phần sánh đúng; c òn $’ là phần c ủa xâu sau phần sánh đúng. Chẳng hạn: $_ = "this is sample string"; /sa.*le/; # sánh "sample" bên trong xâu # $` bây giờ là "this is a " # $& bây giờ là "sample" # $’ bây giờ là " string" Vì tất c ả những biến này đều được đặt lại c ho từng lần sánh thành công c ho nên bạn nên c ất giữ các giá trị trong các biến vô hướng khác nếu bạn c ần c ác giá t rị đó về sau trong chương trình. 7.5 Thay thế Chúng ta đã nói về dạng đơn giản nhất của toán tử thay thế: s/old-regex/new-string/. Bây giờ là lúc nói tới vài biến t hể c ủa toán tử này. Nếu bạn muốn việc thay thế vận hành trên tất c ả c ác đối sánh c ó thể thay vì c hỉ việc đối sánh đầu tiên thì hãy viết thêm g vào toán tử này, như t rong: $_ = "foot fool buffon"; s/foo/bar/g; # $_ bây giờ là "bart barl buffon" Xâu thay thế có biến xen vào, c ho phép bạn xác định xâu thay thế vào lúc c hạy: $_ = "hello, world"; $new = "goodbye"; s/hello/$new/; # t hay thế hello bằng goodbye Các kí tự khuôn mẫu trong biểu thức chính qui c ho phép c ác khuôn mẫu được đối sánh, thay vì chỉ là các kí tự c ố định: $_ = "this is a test"; 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 c ho biểu thức c hính qui trong toán tử thay t hế bỏ qua
  4. Hậu tố i (hoặc trước hoặc sau g nếu c ó) làm c ho biểu thức c hính qui trong toán tử thay t hế bỏ qua chữ hoa thường, giống như c ùng tuỳ c họn trên toán tử đối sánh đã mô t ả trước đây. Cũng vậy, giống như toán tử đối sánh, một dấu định biên khác cũng c ó thể được t uyển lựa nếu sổ chéo là không tiện. Chỉ cần dùng c ùng kí tự đó ba lần: s#jerry#tom#; # t hay jerry bằng tom, giống s/jerry/tom/ Cũng vậy, giống toán tử đối sánh, bạn có thể xác định một mục tiêu thay phiên bằng toán tử =~ . Trong trường hợp này, mục tiêu được c họn phải là một c ái gì đó mà bạn c ó thể gán cho một giá trị vô hướng vào, như một biến vô hướng hay một phần tử c ủa mảng. Sau đây là một thí dụ: $which = "this is a test"; $which =~ s/test/quiz/; # $whic h bây giờ là "this is a quiz" $someplace[$here] =~ s/left/right/; # đổi một phần tử của mảng $d{"t"} =~ s/^ /x /; 7.6 Các toán tử split() và join() Biểu thức c hính qui c ó thể được dùng để chặt một xâu thành các trường. Toán tử split() t hự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. 7.6.1 Toán tử split() Toán tử s plit() 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ức chí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 c hính qui sẽ được trả về lần lượt như một danh sác h c ác giá trị. Chẳng hạn, sau đây là một c ác h phân tíc h c ác thành tố t rong file /etc /passwd: $line = "merlyn::118:10:Jenny:/home/merlyn:/usr/bin/perl"; @fields = split(/:/,$line); # c hặt $line ra, dùng : làm dấu định biên # bây giờ @field là ("merlyn", "", "118", "10", "Jenny", "/home/merlyn", "/usr/bin/perl") Lưu ý rằng trường thứ hai rỗng trở thành một xâu rỗng. Nếu bạn không muốn điều này, hãy đối sánh tất c ả c ác hai c hấm trong một lần phân tác h: @fields = split(/:+/, $line); Điều này sẽ sánh c ả hai dấu hai c hấm đi kèm, c ho nên sẽ không có trường thứ hai rỗng nữa. Một xâu thông dụng để c hặt biến $_, và biến thành mặc định là: $_ = "any string"; @words = split(/ /); # hệt như @words = split(/ /, $_); Lưu ý rằng đối với việc c hặt này, các khoảng c ác h liên tiếp trong xâu c ần c hặt sẽ gây ra các trường không (xâu rỗng) trong kết quả. Một khuôn mẫu tốt hơn sẽ là / +/, hay một c ách lí tưởng /\s+/, mà sẽ đối sánh một hay nhiều kí tự khoảng trắng. Trong thực tế, khuôn mẫu này là khuôn mẫu mặc định, c ho nên nếu bạn định chặt biến $_ theo c ác khoảng trắng, thì bạn c ó thể dùng tất c ả c ác mặc định và đơn thuần nói: @words = split; # hệt như @words = split(/\s+/, $_); Các trường theo sau rỗng không trở thành một phần c ủa danh sác h. Điều này nói c hung không c ần quan tâm-một giải pháp giống thế này: $line = "merlyn::118:10:Jenny:/home/merlyn:/usr/bin/perl"; ($name,$password, $uid,$gid,$gcos,$home,$shell) = split(/:/, $line); # c hặt $line ra bằng c ác h dùng : làm dấu định biên Sẽ đơn thuần c ho $shell một giá trị rỗng (undef) nếu dòng này không đủ dài, hay nếu nó c hứa các giá trị rỗng trong trường cuối (c ác trường phụ thì im lặng bị bỏ qua, vì việc gán danh sác h làm việc theo các h đó). 7.6.2 Toán tử join() Toán tử join() nhận một danh sác h c ác giá trị và gắn c húng lại với nhau dùng xâu gắn giữa từng phần tử danh sác h. Nó trông tựa như thế này: $bigstring = join($glue, @list);
  5. $bigstring = join($glue, @list); Chẳng hạn, để xây dựng lại dòng mật hiệu, bạn hãy thử một các h kiểu như: $outline = join(":", @fields); Lưu ý rằng xâu gắn không phải là biểu thức c hính qui - c hỉ là một xâu bình t hường gồm không hay nhiều kí tự. 7.7 Bài tập 1. Bạn hãy viết 1 biểu thức c hính qui mà nó sánh: ít nhất 1 ký tự a, theo sau là một số lượng bất kỳ c ác ký tự b một số lượng bất kỳ c ác dấu sổ c héo ngược (\) t heo sau là một số lượng bất kỳ c ác dấu hoa thị (* ) ba lần xuất hiện liên tiếp c ủa $whatever. bất kỳ 5 ký tự nào, kể cả ký tự xuống dòng một từ được lặp lại 2 lần (hoặc nhiều hơn) trên cùng 1 dòng. 2. Bạn hãy viết 1 c hương trình đọc vào danh sác h c ác từ ở , và t ìm xem thử có dòng nào c hứa c ả 5 nguyên âm a,e,i,o,u hay không. Nếu c ó hãy in dòng đó ra màn hình. Bạn hãy chạy thử c hương trình với tệp số liệu /usr/dict/words perl myprog.pl < /usr/dict/words (tệp /usr/dict/words c ó trên c ác máy linux và unix, nếu máy bạn không có tệp này, bạn c ó thể tự tạo c ho mình 1 tệp số liệu mẫu để chạy thử chương trình)
ADSENSE

CÓ THỂ BẠN MUỐN DOWNLOAD

 

Đồng bộ tài khoản
2=>2