Tải bản đầy đủ (.docx) (32 trang)

Giới thiệu Perl

Bạn đang xem bản rút gọn của tài liệu. Xem và tải ngay bản đầy đủ của tài liệu tại đây (185.83 KB, 32 trang )

Giới thiệu perl
Lịch sử Perl
Perl là cách viết tắt cho Practical Extraction and Report Language Ngôn ngữ
báo cáo và trích rút thực hành, mặc dầu nó cũng còn đợc gọi là Pathologically
Eclectic Rubbish Lister - Bộ làm danh sách chiết trung bậy bạ và bệnh hoạn. Chẳng
ích gì mà biện minh xem cách gọi nào đúng hơn, vì cả hai đều đợc Larry Wall, ngời
sáng tạo và kiến trúc s chính, ngời cài đặt và bảo trì của Perl chấp nhận. Ông ấy đã
tạo ra Perl khi cố gắng sản xuất ra một số báo cáo từ một cấp bậc các tệp kiểu nh th
ngời dùng mạng Usenet về hệ thống báo lỗi, và lệnh awk làm xì hết hơi. Larry, một
ngời lập trình lời biếng, quyết định thanh toán vấn đề này bằng một công cụ vạn năng
mà anh có thể dùng ít nhất cũng ở một nơi khác. Kết quả là bản đầu tiên của Perl.
Say khi chơi với bản đầu này của Perl một chút, thêm chất liệu đây đó, Larry đa
nó cho cộng đồng độc giả Usenet, thờng vẫn đợc gọi là the Net. Ngời dùng thuộc
toán phù du nghèo khó về hệ thống trên toàn thế giới (quãng độ chục nghìn ngời) đa
lại cho anh phản hồi, hỏi cách làm thế này thế kia, việc này việc khác, nhiều điểm mà
Larry cha bao giờ mờng tợng ra về việc giải quyết cho Perl nhỏ bé của mình cả.
Nhng kết quả là Perl trởng thành, trởng thành và trởng thành thêm nữa, và cũng
cùng tỉ lệ nh lõi của UNIX. (với bạn là ngời mới, toàn bộ lõi UNIX đợc dùng chỉ khít
vào trong 32K! Và bây giờ chúng ta may mắn nếu ta có thể có đợc nó dới một vài
mega.) Nó đã trởng thành trong các tính năng. Nó đã trởng thành trong tính khả
chuyển. Điều mà có thời là một ngôn ngữ tí tẹo bây giờ đã có tài liệu sử dụng 80
trang, một cuốn sách của Nutshell 400 trang, một nhóm tin Usenet với 40 nghìn thuê
bao, và bây giờ là đoạn giới thiệu nhẹ nhàng này.
Larry vẫn là ngời bảo trì duy nhất, làm việc trên Perl ngoài giờ khi kết thúc công
việc thờng ngày của mình. Và Perl thì vẫn phát triển.
Một cách đại thể thì lúc mà cuốn sách này đạt tới điểm dừng của nó, Larry sẽ đa
ra bản Perl mới nhất, bản 5.0, hứa hẹn có một số tính năng thờng hay đợc yêu cầu, và
đợc thiết kế lại từ bên trong trở ra. (Larry bảo tôi rằng không còn mấy dòng lệnh từ
lần đa ra trớc, và số ấy cứ ngày càng ít đi mỗi ngày.) Tuy nhiên, cuốn sách này đã đợc
thử với Perl bản 4.0 (lần đa ra gần đây nhất khi tôi viết điều này). Mọi thứ ở đây đều
sẽ làm việc với bản 5.0 và các bản sau của Perl. Trong thực tế, chơng trình Perl 1.0


vẫn làm việc tốt với những bản gần đây, ngoại trừ một vài thay đổi lạ cần cho sự tiến
bộ.
Mục đích của Perl
Perl đợc thiết kế để trợ giúp cho ngời dùng UNIX với những nhiệm vụ thông
dụng mà có thể rất nặng nề hay quá nhậy cảm với tính khả chuyển đối với trình vỏ, và
cũng quá kì lạ hay ngắn ngủi hay phức tạp để lập trình trong C hay một ngôn ngữ
công cụ UNIX nào khác.
Một khi bạn trở nên quen thuộc với Perl, bạn có thể thấy mình mất ít thời gian để
lấy đợc trích dẫn trình vỏ (hay khai báo C) đúng, và nhiều thời gian hơn để đọc tin
trên Usenet và đi trợt tuyết trên đồi; vì Perl là một công cụ lớn tựa nh chiếc đòn bẩy.
Các cấu trúc chặt chẽ của Perl cho phép bạn tạo ra (với tối thiểu sự om sòm nhặng sị)
một số giải pháp có u thế rất trần lặng hay những công cụ tổng quát. Cũng vậy, bạn
có thể lôi những công cụ này sang công việc tiếp, vì Perl là khả chuyển cao độ và lại
có sẵn, cho nên bạn sẽ có nhiều thời gian hơn để đọc tin Usenet và trợt tuyết.
Giống nh mọi ngôn ngữ, Perl có thể chỉ viết - tức là có thể viết ra chơng trình
mà không thể nào đọc đợc. Nhng với sự chú ý đúng đắn, bạn có thể tránh đợc sự kết
tội thông thờng này. Quả thế, đôi khi Perl trông nh nổi tiếng với những cái không
quen thuộc, nhng với ngời lập trình đã thạo Perl, nó tựa nh những dòng có tổng kiểm
tra với một sứ mệnh trong cuộc đời. Nếu bạn tuân theo những hớng dẫn của cuốn
sách này thì chơng trình của bạn sẽ dễ đọc và dễ bảo trì, và chúng có lẽ sẽ không
thắng trong bất kì cuộc tranh luận Perl khó hiểu nào.
Tính sẵn có
Nếu bạn nhận đợc
Perl: not found
khi bạn thử gọi Perl từ lớp vỏ thì ngời quản trị hệ thống của bạn cũng chẳng lên cơn
sốt. Nhng thậm chí nếu nó không có trên hệ thống của bạn, thì bạn vẫn có thể lấy đợc
nó không mất tiền (theo nghĩa ăn tra không mất tiền).
Perl đợc phân phối theo phép công cộng GNU, nghĩa là thế này, bạn có thể phân
phát chơng trình nhị phân Perl chỉ nếu bạn làm ra chơng trình gốc có sẵn cho mọi ng-
ời dùng không phải trả tiền gì cả, và nếu bạn sửa đổi Perl, bạn phải phân phát chơng

trình gốc của bạn cho nơi sửa đổi của bạn nữa. Và đó là bản chất của cho không.
Bạn có thể lấy chơng trình gốc của Perl với giá của một băng trắng hay vài mêga byte
qua đờng dây. Và không ai có thể khoá Perl và bán cho bạn chỉ mã nhị phân với ý t-
ởng đặc biệt về cấu hình phần cứng đợc hỗ trợ.
Trong thực tế, nó không chỉ là cho không, nhng nó chạy còn gọn hơn trên gần nh
mọi thứ mà có thể gọi là UNIX hay tựa UNIX và có trình biên dịch C. Đấy là vì bộ
trình này tới với bản viết cấu hình bí quyết đợc gọi là Cấu hình, cái sẽ móc và chọc
vào các danh mục hệ thống để tìm những thứ nó cần, và điều chỉnh việc đa vào các
tệp và các kí hiệu đợc xác định tơng ứng, chuyển cho bạn việc kiểm chứng phát hiện
của nó.
Bên cạnh các hệ thống UNIX hay tựa UNIX, ngời đã bị nghiện Perl đem nó sang
Amiga, Atari ST, họ Macintosh, VMS, OS/2, thậm chí MS/DOS - và có lẽ còn nhiều
hơn nữa vào lúc bạn đọc cuốn sách này. Vị trí chính xác và sự có sẵn của những bản
Perl này thì biến động, cho nên bạn phải hỏi quanh (trên nhóm tin Usenet chẳng hạn)
để có đợc thông tin mới nhất. Nếu bạn hoàn toàn không biết gì, thì một bản cũ của
Perl đã có trên đĩa phần mềm CD-ROM UNIX Power Tools, của Jerry Peek, Tim
OReilly và Mike Loukides (OReilly & Associates/ Random House Co., 1993).
Hỗ trợ
Perl là con đẻ của Larry Wall, và vẫn đang đợc anh ấy nâng niu. Báo cáo lỗi và
yêu cầu nâng cao nói chung đều đợc sửa chữa trong các lần đa ra sau, nhng anh ấy
cũng chẳng có nghĩa vụ nào để làm bất kì cái gì với chúng cả. Tuy thế Larry thực sự
thích thú nghe từ tất cả chúng ta, và cũng làm việc thực sự để thấy Perl đợc dùng trên
qui mô thế giới. E-mail trực tiếp cho anh ấy nói chung đều nhận đợc trả lời (cho dù
đấy chỉ đơn thuần là máy trả lời email của anh ấy), và đôi khi là sự đáp ứng con ngời.
ích lợi hơn việc viết th trực tiếp cho Larry là nhóm hỗ trợ Perl trực tuyến toàn thế
giới, liên lạc thông qua nhóm tin Usenet comp.lang.perl. Nếu bạn có thể gửi email
trên Internet, nhng cha vào Usenet, thì bạn có thể tham gia nhóm này bằng cách gửi
một yêu cầu tới , yêu cầu sẽ tới một ngời có thể nối
bạn với cửa khẩu email hai chiều trong nhóm, và cho bạn những hứong dẫn về cách
làm việc.

Khi bạn tham gia một nhóm tin, bạn sẽ thấy đại loại có khoảng 30 đến 60 th
mỗi ngày (vào lúc bản viết này đợc soạn thảo) trên đủ mọi chủ đề từ câu hỏi của ngời
mới bắt đầu cho tới vấn đề chuyển chơng trình phức tạp và vấn đề giao diện, và thậm
chí cả một hay hai chơng trình khá lớn.
Nhóm tin gần nh đợc những chuyên gia Perl điều phối. Phần lớn thời gian, câu
hỏi của bạn đều có sự trả lời trong vòng vài phút khi bài tin bạn tới tủ nối Usenet
chính. Bạn hãy thử mức độ hỗ trợ từ nhà sản xuất phần mềm mình a chuộng về việc
cho không này! Bản thân Larry cũng đọc về nhóm khi thời gian cho phép, và đôi khi
đã xen các bài viết có thẩm quyền vào để chấm dứt việc cãi nhau hay làm sáng tỏ một
vấn đề. Sau rốt, không có Usenet, có lẽ không thể có chỗ để dễ dàng công bố Perl cho
cả thế giới.
Bên cạnh nhóm tin, bạn cũng nên đọc tạp chí Perl, đi cùng việc phân phối Perl.
Một nguồn có thẩm quyền khác là cuốn sách Programming Perl của Larry Wall và
Randal L. Schwatrz (OReilly & Associaté, 1990). Programming Perl đợc xem nh
Sách con lừa vì bìa của nó vẽ con vật này (hệt nh cuốn sách này có lẽ sẽ đợc biết tới
với tên sách lạc đà không bớu). Sách con lừa chứa thông tin tham khảo đầy đủ về Perl
dới dạng đóng gọn gàng. Sách con lừa cũng bao gồm một bảng tra tham khảo bật ra
tài tình mà chính là nguồn a chuộng của cá nhân tôi về thông tin Perl.
Các khái niệm cơ bản
Một bản viết vỏ không gì khác hơn là một dãy các lệnh vỏ nhồi vào trong một tệp
văn bản. Tệp này đợc làm cho chạy bằng cách bật một bit thực hiện (qua chmod +x
filename) và rồi gõ tên của tệp đó vào lời nhắc của vỏ. Bingo, một chơng trình vỏ lớn.
Chẳng hạn, một bản viết để chạy chỉ lệnh date theo sau bởi chỉ lệnh who có thể đợc
tạo ra và thực hiện nh thế này:
$ echo date > somecript
$ echo who > somecript
$ cat somescript
date
who
$ chmod _x somescript

$ somescript
[output of date followed by who]
$
Tơng tự nh thế, một chơng trình Perl là một bó các câu lệnh và định nghĩa Perl đ-
ợc ném vào trong một tệp. Rồi bạn bật bit thực hiện và gõ tên của tệp này tại lời nhắc
của vỏ. Tuy nhiên, tệp này phải chỉ ra rằng đây là một chơng trình Perl và không phải
là chơng trình vỏ, nên chúng ta cần một bớc phụ.
#! /usr/bin/perl
làm dòng đầu tiên của tệp này. Nhng nếu Perl của bạn bị kẹt vào một nơi không
chuẩn, hay hệ điều hành tựa UNIX của bạn không hiểu dòng #!, thì bạn có thêm việc
phải làm. Hãy hỏi ngời cài đặt Perl về điều này. Các thí dụ trong sách này giả sử rằng
bạn dùng cơ chế thông thờng này.
Perl là một ngôn ngữ phi định dạng kiểu nh C - khoảng trắng giữa các hiệu bài
(những phần tử của chơng trình, nh print hay +) là tuỳ chọn, trừ phi hai hiệu bài đi với
nhau có thể bị lầm lẫn thành một hiệu bài khác, trong trờng hợp đó thì khoảng trắng
thuộc loại nào đó là bắt buộc. (Khoảng trắng bao gồm dấu cách, dấu tab, dòng mới,
về đầu dòng hay kéo giấy.) Có một vài cấu trúc đòi hỏi một loại khoảng trắng nào đó
ở chỗ nào đó, nhng chúng sẽ đợc trỏ ra khi ta nói tới chúng. Bạn có thể giả thiết rằng
loại và khối lợng khoảng trắng giữa các hiệu bài là tuỳ ý trong các trờng hợp khác.
Mặc dầu gần nh tất cả các chơng trình Perl đều có thể đợc viết tất cả trên một
dòng, một cách điển hình chơng trình Perl cũng hay đợc viết tụt lề nh chơng trình C,
với những phần câu lệnh lồng nhau đợc viết tụt vào hơn so với phần bao quanh. Bạn
sẽ thấy đầy những thí dụ chỉ ra phong cách viết tụt lề điển hình trong toàn bộ cuốn
sách này.
Cũng giống nh bản viết về vỏ, chơng trình Perl bao gồm tất cả các câu lệnh perl
về tệp đợc lấy tổ hợp chung nh mọt trình lớn cần thực hiện. Không có khái niệm về
trình chính main nh trong C.
Chú thích của Perl giống nh chú thích của lớp vỏ (hiện đại). Bất kì cái gì nằm
giữa một dấu thăng (#) tới cuối dòng đều là một chú thích. Không có khái niệm về
chú thích trên nhiều dòng nh C.

Không giống hầu hết các lớp vỏ (nhng giống nh awk và sed), bộ thông dịch Perl
phân tích và biên dịch hoàn toàn chơng trình trớc khi thực hiện nó. Điều này có nghĩa
là bạn không bao giờ nhận đợc lỗi cú pháp từ chơng trình một khi chơng trình đã bắt
đầu chạy, và cũng có nghĩa là khoảng trắng và chú thích biến mất và sẽ không làm
chậm chơng trình. Trong thực tế, giai đoạn biên dịch này bảo đảm việc thực hiện
nhanh chóng của các thao tác Perl một khi nó đợc bắt đầu, và nó cung cấp động cơ
phụ để loại bỏ C nh một ngôn ngữ tiện ích hệ thống đơn thuần dựa trên nền tảng là C
đợc biên dịch.
Việc biên dịch này không mất thời gian - sẽ là phi hiệu quả nếu một chơng trình
Perl cực lớn lại chỉ thực hiện một nhiệm vụ nhỏ bé chóng vánh (trong số nhiều nhiệm
vụ tiềm năng) và rồi ra, vì thời gian chạy cho chơng trình sẽ nhỏ xíu nếu so với thời
gian dịch.
Cho nên Perl giống nh một bộ biên dịch và thông dịch. Nó là biên dịch vì chơng
trình đợc đọc và phân tích hoàn toàn trớc khi câu lệnh đầu tiên đợc thực hiện. Nó là
bộ thông dịch vì không có mã đích ngồi đâu đó trút đầy không gian đĩa. Theo một
cách nào đó, nó là tốt nhất cho cả hai loại này. Phải thú thực, việc ẩn đi mã đích đã
dịch giữa những lời gọi thì hay, và đó là trong danh sách mong ớc cho Perl tơng lai
của Larry.
Dạo qua Perl
Chúng ta bắt đầu cuộc hành trình của mình qua Perl bằng việc đi dạo một chút.
Việc đi dạo này sẽ giới thiệu một số các tính năng khác nhau bằng cách bổ sung vào
một ứng dụng nhỏ. Giải thích ở đây là cực kì ngắn gọn - mỗi vùng chủ đề đều đợc
thảo luận chi tiết hơn rất nhiều về sau trong cuốn sách này. Nhng cuộc đi dạo nhỏ
này sẽ cho bạn kinh nghiệm nhanh chóng về ngôn ngữ, và bạn có thể quyết định liệu
bạn có thực sự muốn kết thúc cuốn sách này hay đọc thêm các tin Usenet hay chạy đi
chơi trợt tuyết.
Chơng trình Xin chào mọi ngời
Ta hãy nhìn vào một chơng trình nhỏ mà thực tế có làm điều gì đó. Đây là chơng
trình Xin chào mọi ngời:
#!/usr/bin/perl

print Xin chào mọi ngời\n;
Dòng đầu tiên là câu thần chú nói rằng đây là chơng trình Perl. Nó cũng là lời chú
thích cho Perl - hãy nhớ rằng lời chú thích là bất kì cái gì nằm sau dấu thăng cho tới
cuối dòng, giống nh hầu hết các lớp vỏ hiện đại hay awk.
Dòng thứ hai là toàn bộ phần thực hiện đợc của chơng trình này. Tại đây chúng ta
thấy câu lệnh print. Từ khoá print bắt đầu chơng trình, và nó có một đối, một xâu văn
bản kiểu C. Bên trong xâu này, tổ hợp kí tự \n biểu thị cho kí tự dòng mới; hệt nh
trong C. Câu lệnh print đợc kết thúc bởi dấu chấm phẩy (;). Giống nh C, tất cả các câu
lệnh đơn giản đều kết thúc bằng chấm phẩy
*
.
Khi bạn gọi chơng trình này, phần lõi sẽ gọi bộ thông dịch Perl, phân tích câu
*
*
Dấu chấm phẩy có thể bỏ đi khi câu lệnh này là câu lệnh cuối của một khối hay tệp hay eval.
toàn bộ chơng trình (hai dòng, kể cả dòng chú thích đầu tiên) và rồi thực hiện dạng đã
dịch. Thao tác đầu tiên và duy nhất là thực hiện toán tử print, điều này gửi đối của nó
ra lối ra. Sau khi chơng trình đã hoàn tất, thì tiến trình Perl ra, cho lại một mã ra
thành công cho lớp vỏ.
Hỏi câu hỏi và nhớ kết quả
Ta hãy thêm một chút phức tạp hơn. Từ Xin chào mọi ngời là một sự đụng chạm
lạnh nhạt và cứng rắn. Ta hãy làm cho chơng trình gọi bạn theo tên bạn. Để làm việc
này, ta cần một chỗ giữ tên, một cách hỏi tên, và một cách nhận câu trả lời.
Một loại đặt chỗ giữ giá trị (tựa nh một tên) là biến vô hớng. Với chơng trình này,
ta sẽ dùng biến vô hớng $name để giữ tên bạn. Chúng ta sẽ đi chi tiết hơn trong Ch-
ơng 2, Dữ liệu vô hớng, về những gì mà biến này có thể giữ, và những gì bạn có thể
làm với chúng. Hiện tại, giả sử rằng bạn có thể giữ một số hay xâu (dãy các kí tự)
trong biến vô hớng.
Chơng trình này cần hỏi về tên. Để làm điều đó, ta cần một cách nhắc và một
cách nhận cái vào. Chơng trình trớc đã chỉ ra cho ta cách nhắc - dùng toán tử print. Và

cách để nhận một dòng từ thiết bị cuối là với toán tử <STDIN>, mà (nh ta sẽ dùng nó
ở đây) lấy một dòng cái vào. Ta gán cái vào này cho biến $name. Điều này cho ta ch-
ơng trình:
print Tên bạn là gì? : ;
$name = <STDIN> ;
Giá trị của $name tại điểm này có một dấu dòng mới kết thúc (Randal có trong
Randal\n). Để vứt bỏ điều đó, chúng ta dùng toán tử chop(), toán tử lấy một biến vô h-
ớng làm đối duy nhất và bỏ đi kí tự cuối từ giá trị xâu của biến:
chop($name);
Bây giờ tất cả những gì ta cần làm là nói Xin chào, tiếp đó là giá trị của biến
$name, mà ta có thể thực hiện theo kiểu vỏ bằng cách nhúng biến này vào bên trong
xâu có ngoặc kép:
print Xin chào, $name!\n;
Giống nh lớp vỏ, nếu ta muốn một dấu đô la thay vì tham khảo biến vô hớng, thì
ta có thể đặt trớc dấu đô la với một dấu sổ chéo ngợc.
Gắn tất cả lại, ta đợc:
#!/usr/bin/perl
print Tên bạn là gì? ;
$name = <STDIN> ;
chop($name);
print Xin chào, $name!\n;
Bổ sung chọn lựa
Bây giờ ta muốn có một lời chào đặc biệt cho Randal, nhng muốn lời chào thông
thờng cho mọi ngời khác. Để làm điều này, ta cần so sánh tên đã đợc đa vào với xâu
Randal, và nếu hai xâu là một, thì làm điều gì đó đặc biệt. Ta hãy bổ sung thêm lệnh
rẽ nhánh if-then-else và phép so sánh vào chơng trình:
#!/usr/bin/perl
print Tên bạn là gì? ;
$name = <STDIN> ;
chop($name);

if ($name eq Randal) {
print Xin chào Randal! Tốt quá anh lại ở đây!\n;
} else {
print Xin chào, $name!\n; # chào mừng thông thờng
}
Toán tử eq so sánh hai xâu. Nếu chúng bằng nhau (từng kí tự một, và có cùng
chiều dài), thì kết quả là đúng. (Không có toán tử này trong C, và awk phải dùng
cùng toán tử cho xâu và số và tạo ra việc đoán có rèn luyện.)
Câu lệnh if chọn xem khối câu lệnh nào (giữa các dấu ngoặc nhọn sánh đúng) là
đợc thực hiện - nếu biểu thức là đúng, đó là khối thứ nhất, nếu không thì đó là khối
thứ hai.
Đoán từ bí mật
Nào, vì chúng ta đã có một tên nên ta hãy để cho một ngời chạy chơng trình đoán
một từ bí mật. Với mọi ngời ngoại trừ Randal, chúng ta sẽ để cho chơng trình cứ hỏi
lặp lại để đoán cho đến khi nào ngời này đoán đợc đúng. Trớc hết ta hãy xem chơng
trình này và rồi xem giải thích:
#! /usr/bin/perl
$secretword = llama; # từ bí mật
print Tên bạn là gì? ;
$name = <STDIN> ;
chop($name);
if ($name eq Randal) {
print Xin chào, Randal! May quá anh ở đây!\n;
} else {
print Xin chào, $name!\n ; # chào thông th ờng
print Từ bí mật là gì? ;
$guess = <STDIN>;
chop($guess);
while ($guess ne $secrectword) {
print Sai rồi, thử lại đi. Từ bí mật là gì?;

$guess = <STDIN>;
chop($guess);
}
}
Trớc hết, ta định nghĩa từ bí mật bằng việc đặt nó vào trong biến vô hớng khác,
$secretword. Sau khi đón chào, một ngời (không phải Randal) sẽ đợc yêu cầu (với một
câu lệnh print khác) đoán chữ. Lời đoán rồi đợc đem ra so sánh với từ bí mật bằng
việc dùng toán tử ne, mà sẽ cho lại đúng nếu các xâu này không bằng nhau (đây là
toán tử logic ngợc với toán tử eq). Kết quả của việc so sánh sẽ kiểm soát cho trình
while, chu trình này thực hiện khối thân cho tới khi việc so sánh vẫn còn đúng.
Tất nhiên, chơng trình này không phải là an toàn lắm, vì bất kì ai mệt với việc
đoán cũng đều có thể đơn thuần ngắt chơng trình và quay trở về lời nhắc, hay thậm
chí còn nhìn qua chơng trình gốc để xác định ra từ. Nhng, chúng ta hiện tại cha định
viết một hệ thống an toàn, chỉ xem nh một thí dụ cho trang hiện tại của cuốn sách
này.
Nhiều từ bí mật
Ta hãy xem cách thức mình có thể sửa đổi đoạn chơng trình này để cho phép có
nhiều từ bí mật. Bằng việc dùng điều ta đã thấy, chúng ta có thể so sánh lời đoán lặp
đi lặp lại theo một chuỗi câu trả lời rõ đợc cất giữ trong các biến vô hớng tách biệt.
Tuy nhiên, một danh sách nh vậy sẽ khó mà thay đổi hay đọc vào từ một tệp hay máy
tính trên cơ sở ngày làm việc thờng lệ.
Một giải pháp tốt hơn là cất giữ tất cả các câu trả lời có thể vào trong một cấu trúc
dữ liệu gọi là danh sách hay mảng. Mỗi phần tử của mảng đều là một biến vô hớng
tách biệt mà có thể đợc đặt giá trị hay thâm nhập độc lập. Toàn bộ mảng cũng có thể
đợc trao cho một giá trị trong một cú đột nhập. Ta có thể gán một giá trị cho toàn bộ
mảng có tên @words sao cho nó chứa ba mật hiệu tốt có thể có:
@words = (camel, llama, oyster);
Tên biến mảng bắt đầu với @, cho nên chúng là khác biệt với các tên biến vô h-
ớng.
Một khi mảng đã đợc gán thì ta có thể thâm nhập vào từng phần tử bằng việc

dùng một tham khảo chỉ số. Cho nên $words[0] là camel, $words[1] là llama, $words[2]
là oyster. Chỉ cố cũng có thể là một biểu thức, cho nên nếu ta đặt $i là 2 thì $words[$i]
là oyster. (Tham khảo chỉ số bắt đầu với $ thay vì @ vì chúng tham khảo tới một phần
tử riêng của mảng thay vì toàn bộ mảng.) Quay trở lại với thí dụ trớc đây của ta:
#! /usr/bin/perl
$words = (camel, llama, oyster); # từ bí mật
print Tên bạn là gì? ;
$name = <STDIN> ;
chop($name);
if ($name eq Randal) {
print Xin chào, Randal! May quá anh ở đây!\n;
} else {
print Xin chào, $name!\n; # chào thông thờng
print Từ bí mật là gì? ;
$guess = <STDIN>;
chop($guess);
$i = 0; # thử từ này trớc hết
$correct = có thể; # từ đoán có đúng hay không?
while ($correct eq $guess) { # cứ kiểm tra đến khi biết
if ($words[$i] eq $guess) { # đúng không
$correct = có; # có
} elsif ($i < 2) { # cần phải xét thêm từ nữa?
$i = $i + 1; # nhìn vào từ tiếp lần sau
} else # hết rồi, thế là hỏng
print Sai rồi, thử lại đi. Từ bí mật là gì?;
$guess = <STDIN>;
chop($guess);
$i = 0; # bắt đầu kiểm tra từ đầu lần nữa
}
} # kết thúc của while not correct

} # kết thúc của not Randal
Bạn sẽ để ý rằng chúng ta đang dùng biến vô hớng $correct để chỉ ra rằng chúng
ta vẫn đang tìm ra mật hiệu đúng, hay rằng chúng ta không tìm thấy.
Chơng trình này cũng chỉ ra khối elsif của câu lệnh if-then-else. Không có lệnh nào
tơng đơng nh thế trong C hay awk - đó là việc viết tắt của khối else cùng với một điều
kiện if mới, nhng không lồng bên trong cặp dấu ngoặc nhọn khác. Đây chính là cái rất
giống Perl để so sánh một tập các điều kiện trong một dây chuyền phân tầng if-elsif-
elsif-elsif-else.
Cho mỗi ngời một từ bí mật khác nhau
Trong chơng trình trớc, bất kì ngời nào tới cũng đều có thể đoán bất kì từ nào
trong ba từ này và có thể thành công. Nếu ta muốn từ bí mật là khác nhau cho mỗi
ngời, thì ta cần một bảng sánh giữa ngời và từ:
Ngời Từ bí mật
Fred Camel
Barney
Betty
Wilma
Llama
Oyster
Oyster
Chú ý rằng cả Betty và Wilma đều có cùng từ bí mật. Điều này là đợc.
Cách dễ nhất để cất giữ một bảng nh thế trong Perl là bằng một mảng kết hợp.
Mỗi phần tử của mảng này giữ một giá trị vô hớng tách biệt (hệt nh kiểu mảng khác),
nhng các mảng lại đợc tham khảo tới theo khoá, mà có thể là bất kì giá trị vô hớng
nào (bất kì xâu hay số, kể cả số không nguyên và giá trị âm). Để tạo ra một mảng kết
hợp đợc gọi là %words (chú ý % chứ không phải là @) với khoá và giá trị đợc cho
trong bảng trên, ta gán một giá trị cho %words (nh ta đã làm nhiều trớc đây với mảng
khác):
%words = (fred, camel, barney, llama,
betty, oyster, wilma, oyster) ;

Mỗi cặp giá trị trong danh sách đều biểu thị cho một khoá và giá trị tơng ứng của
nó trong mảng kết hợp. Chú ý rằng ta đã bẻ phép gán này ra hai dòng mà không có
bất kì loại kí tự nối dòng nào, vì khoảng trắng nói chung là vô nghĩa trong chơng
trình Perl.
Để tìm ra từ bí mật cho Betty, ta cần dùng Betty nh khoá trong một tham khảo vào
mảng kết hợp %words, qua một biểu thức nào đó nh %words{betty}. Giá trị của tham
khảo này là oyster, tơng tự nh điều ta đã làm trớc đây với mảng khác. Cũng nh trớc
đây, khoá có thể là bất kì biểu thức nào, cho nên đặt $person với betty và tính
$words{$person} cũng cho oyster.
Gắn tất cả những điều này lại ta đợc chơng trình nh thế này:
#! /usr/bin/perl
%words = (fred, camel, barney, llama,
betty, oyster, wilma, oyster) ;
print Tên bạn là gì? ;
$name = <STDIN> ;
chop($name);
if ($name eq Randal) {
print Xin chào, Randal! May quá anh ở đây!\n;
} else {
print Xin chào, $name!\n; # chào thông thờng
$secretword = $words{$name}; # lấy từ bí mật
print Từ bí mật là gì? ;
$guess = <STDIN>;
chop($guess);
while ($correct ne $secretwords) {
print Sai rồi, thử lại đi. Từ bí mật là gì? ;
$guess = <STDIN>;
chop($guess);
} # kết thúc của while
} # kết thúc của not Randal

Bạn hãy chú ý nhìn vào từ bí mật. Nếu không tìm thấy từ này thì giá trị của
$secretword sẽ là một xâu rỗng
*
, mà ta có thể kiểm tra liệu ta có muốn xác định một
từ bí mật mặc định cho ai đó khác không. Đây là cách xem nó:
[... phần còn lại của chơng trình đã bị xoá...]
$secretword = $words{$name}; # lấy từ bí mật
if ($secretword eq ) { # ấy, không thấy
$secretword = đồ cáu kỉnh; # chắc chắn, sao không là vịt?
}
print Từ bí mật là gì? ;
[... phần còn lại của chơng trình đã bị xoá...]
Giải quyết định dạng cái vào thay đổi
Nếu tôi đa vào Randal L. Schwartz hay randal thay vì Randal thì tôi sẽ bị đóng cục
lại với phần ngời dùng còn lại, vì việc so sánh eq thì lại so sánh đúng sự bằng nhau.
Ta hãy xem một cách giải quyết cho điều đó.
Giả sử tôi muốn tìm bất kì xâu nào bắt đầu với Randal, thay vì chỉ là một xâu
bằng Randal. Tôi có thể làm điều này trong sed hay awk hoặc grep với một biểu thức
chính qui: một tiêu bản sẽ xác định ra một tập hợp các xâu sánh đúng. Giống nh
trong sed hay grep, biểu thức chính qui trong Perl để sánh bất kì xâu nào bắt đầu với
Randal là ^Randal. Để sánh xâu này với xâu trong $name, chúng ta dùng toán tử sánh
nh sau:
if ($name =~ /^Randal/) {
## có, sánh đúng
} else {
## không, sánh sai
}
Chú ý rằng biểu thức chính qui đợc định biên bởi dấu sổ chéo. Bên trong các dấu
sổ chéo, dấu cách và khoảng trắng là có nghĩa, hệt nh chúng ở bên trong xâu.
Điều này gần nh thế, nhng nó lại không giải quyết việc lựa ra randal hay loại bỏ

Randall. Để chấp nhận randal, chúng ta thêm tuỳ chọn bỏ qua hoa thờng, một chữ i
*
*
Đợc, đấy chính là giá trị undef, nhng nó trông nh một xâu rỗng cho toán tử eq
nhỏ đợc thêm vào sau dấu sổ chéo đóng. Để loại bỏ Randall, ta thêm một đánh dấu
đặc biệt định biên từ (tơng tự với vi và một số bản của grep) dới dạng của \b trong
biểu thức chính qui. Điều này đảm bảo rằng kí tự đi sau l đầu tiên trong biểu thức
chính qui không phải là một kí tự khác. Điều này làm thay đổi biểu thức chính qui
thành /^randal\b/i, mà có nghĩa là randal tại đầu xâu, không có kí tự hay chữ số nào
theo sau, và chấp nhận cả hai kiểu chữ hoa thờng.
Khi gắn tất cả lại với phần còn lại của chơng trình thì nó sẽ giống nh thế này:
#! /usr/bin/perl
%words = (fred, camel, barney, llama,
betty, oyster, wilma, oyster) ;
print Tên bạn là gì? ;
$name = <STDIN> ;
chop($name);
if ($name =~ /^randal\b/i ) {
print Xin chào, Randal! May quá anh ở đây!\n;
} else {
print Xin chào, $name!\n; # chào thông thờng
$secretword = $words{$name}; # lấy từ bí mật
if ($secretword eq ) { # ấy, không thấy
$secretword = đồ cáu kỉnh; # chắc chắn, sao không là vịt?
}
print Từ bí mật là gì? ;
$guess = <STDIN>;
chop($guess);
while ($correct ne $secretwords) {
print Sai rồi, thử lại đi. Từ bí mật là gì?;

$guess = <STDIN>;
chop($guess);
} # kết thúc của while
} # kết thúc của not Randal
Nh bạn có thể thấy, chơng trình này khác xa với chơng trình đơn giản Xin chào,
mọi ngời, nhng nó vẫn còn rất nhỏ bé và làm việc đợc, và nó quả làm đợc tí chút với
cái ngắn xíu vậy. đây chính là cách thức của Perl.
Perl đa ra tính năng về các biểu thức chính qui có trong mọi trình tiện ích UNIX
chuẩn (và thậm chí trong một số không chuẩn). Không chỉ có thế, nhng cách thức
Perl giải quyết cho việc đối sánh xâu là cách nhanh nhất trên hành tin này, cho nên
bạn không bị mất hiệu năng. (Một chơng trình giống nh grep đợc viết trong Perl th-
ờng đánh bại chơng trình grep đợc các nhà cung cấp viết trong C với hầu hết các cái
vào. Điều này có nghĩa là thậm chí grep không thực hiện một việc của nó thật tốt.)

Tài liệu bạn tìm kiếm đã sẵn sàng tải về

Tải bản đầy đủ ngay
×