I. PHẦN MỞ ĐẦU: 1. Giới thiệu: PERL là cách viết tắt cho “Practical Extraction and Report Language” (Ngôn ngữ kết xuất và báo cáo thực dụng), mặc dù còn được gọi là “Pathologically Eclectic Rubbish Lister". Tên gọi: Ban đầu, ngôn ngữ này có tên là "Pearl" (ngọc trai), được đặt tên theo "Parable of the Pearl" trong sách phúc âm. Larry đã bỏ nhiều công sức tìm kiếm tên cho ngôn ngữ mới. Ông đã thử xem xét (và bỏ qua) tất cả các từ 3,4 ký tự trong tự điển. Cuối cùng, ông đã đặt tên Pearl. Nhưng trước ngày phiên bản chính thức đầu tiên của Perl ra đời, Larry phát hiện ra đã có một ngôn ngữ cũng có tên là PEARL, nên ông quyết định đổi tên ngôn ngữ mình thành Perl Biểu tượng: Programming Perl, xuất bản bởi O''Reilly Media, đã đưa ra nơi trang bìa bức ảnh 1 con lạc đà. Từ đó, lạc đà trở thành biểu tượng của ngôn ngữ Perl, cũng như quyển sách đó còn được biết đến dưới cái tên The Camel Book. 2. Lịch sử: Larry Wall đã tạo ra Perl từ năm 1987 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..và đưa ra bản đầu tiên của Perl – Phiên bản 1.0 trên comp.sources.misc vào ngày 18 tháng 12 năm 1987. Sau đó Larry đưa nó cho các độc giả Usenet, thường vẫn được gọi là “the Net”. Kết quả là Perl phát triển dần và cũng cùng tỉ lệ như kernel của UNIX. Nó đã phát triển các tính năng và tính khả chuyển. Phiên bản 2.0 của Perl được công bố năm 1988, có tính năng tốt hơn cho biểu thức chính quy, phiên bản 3.0, công bố năm 1989, bổ sung them sự hỗ trợ các dữ liệu dạng nhị phân. Và hiện nay phiên bản 4.0, ra đời năm 1991 đang được sử dụng rỗng rãi nhất, cùng với sự ra đời của cuốn sách Programming Perl trở thành 1 cuốn cẩm nang tra cứu ngôn ngữ Perl. II. PHÂN TÍCH: 1. Cấu trúc chương trình Perl và các kiểu dữ liệu: 1.1 Cấu trúc chương trình Perl: Một chương trình perl chạy trên Linux thường có cấu trúc sau: #!/usr/bin/perl-wT (Không bắt buộc) { Phần khai báo các câu lệnh } Với : #!/usr/bin/perl đường dẫn đến chương trình thông dịch Perl trên Linux. wT tham số tuỳ chọn, điều này báo cho trình thông dịch perl cảnh báo những vấn đề có thể phát sinh với mã kịch bản và trả về lỗi nếu chúng ta sử dụng các dữ liệu phía ngoài. Tương tự, một chương trình Perl là một bó các câu lệnh và định nghĩa Perl được đưa 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 shell, nên chúng ta cần một bước phụ: đặt #!/usr/bin/perl làm dòng đầu tiên của tệp 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 phần tử của chương trình là tuỳ chọn, trừ phi hai phần tử của chương trình dính liền với nhau có thể bị lầm lẫn thành một cá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, xuống dòng, về đầu dòng hay sang trang mới). 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 đó, nhưng đừng lo, tài liệu sẽ chỉ rõ cho bạn biết là các khoảng trắng phải được đặt như thế nào với số lượng bao nhiêu. Có thể giả thiết rằng loại và số lượng khoảng trắng giữa các phần tử trong chương trình là tuỳ ý trong các trường hợp khác. Mặc dù 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, nhưng một chương trình Perl điển hình được viết xuống dòng và canh lề như chương trình C. Cũng giống như một kịch bản shell, 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ề hàm chính main như trong C. Chú thích của Perl giống như chú thích của kịch bản shell: bất kì cái gì nằm giữa một dấu # tới cuối dòng đều là một chú thích. Perl không có chú thích trên nhiều dòng như C. Không giống hầu hết các shell (nhưng 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 sẽ được lược bỏ 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 nhất đơn thuần dựa trên nền tảng là C được coi là trình biên dịch. Việc biên dịch này khá tiêu tốn thời gian. Và sẽ là phi hiệu quả nếu một chương trình Perl lớn lại chỉ thực hiện một nhiệm vụ nhỏ bé (trong số nhiều nhiệm vụ tiềm năng) và rồi thoát, vì thời gian chạy cho chương trình sẽ "nhỏ xíu" nếu so với thời gian biên 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 chiếm không gian đĩa. Hiểu theo một cách nào đó, nó là tốt nhất cho cả hai loại này. 1.2 Các kiểu dữ liệu và các thao tác trên dữ liệu 1.2.1 Dữ liệu vô hướng: Dữ liệu vô hướng là gì? Vô hướng là loại dữ liệu đơn giản nhất mà Perl thao tác. Một vô hướng thì hoặc là một số (giống như 4 hay 3.25e20) hay một xâu các kí tự (giống Xin chào hay Gettysburg Address). Một giá trị vô hướng có thể được tác động bởi các toán tử (giống như phép cộng hay ghép), và kết quả trả về nói chung là một kết quả vô hướng. Một giá trị vô hướng có thể được cất giữ vào trong một biến vô hướng. Các biến vô hướng có th
Trang 1PHÂN CÔNG NHIỆM VỤ:
1: Cấu trúc chương trình Perl, Các kiểu dữ liệu
2: Các thao tác trên dữ liệu
3: Các lệnh vào/ra dữ liệu
5: Các lệnh điều khiển chương trình
6: Khai báo và sử dụng chương trình con
MỤC LỤC
1 Giới thiệu
Trang 24 Các lệnh điều khiển chương trình
5 Khai báo và sử dụng chương trình con
6 Lien ket co su du lieu
III KẾT LUẬN:
1 Ý nghĩa
2 Tương lai phát triển
Trang 3I PHẦN MỞ ĐẦU:
1 Giới thiệu:
PERL là cách viết tắt cho “Practical Extraction and Report Language” (Ngôn ngữ kếtxuất và báo cáo thực dụng), mặc dù còn được gọi là “Pathologically Eclectic RubbishLister"
Tên gọi:
Ban đầu, ngôn ngữ này có tên là "Pearl" (ngọc trai), được đặt tên theo "Parable of thePearl" trong sách phúc âm Larry đã bỏ nhiều công sức tìm kiếm tên cho ngôn ngữ mới.Ông đã thử xem xét (và bỏ qua) tất cả các từ 3,4 ký tự trong tự điển Cuối cùng, ông đãđặt tên Pearl Nhưng trước ngày phiên bản chính thức đầu tiên của Perl ra đời, Larryphát hiện ra đã có một ngôn ngữ cũng có tên là PEARL, nên ông quyết định đổi tênngôn ngữ mình thành Perl
18 tháng 12 năm 1987 Sau đó Larry đưa nó cho các độc giả Usenet, thường vẫn đượcgọi là “the Net” Kết quả là Perl phát triển dần và cũng cùng tỉ lệ như kernel của UNIX
Nó đã phát triển các tính năng và tính khả chuyển Phiên bản 2.0 của Perl được công bốnăm 1988, có tính năng tốt hơn cho biểu thức chính quy, phiên bản 3.0, công bố năm
1989, bổ sung them sự hỗ trợ các dữ liệu dạng nhị phân Và hiện nay phiên bản 4.0, rađời năm 1991 đang được sử dụng rỗng rãi nhất, cùng với sự ra đời của cuốn sách
Programming Perl trở thành 1 cuốn cẩm nang tra cứu ngôn ngữ Perl.
II PHÂN TÍCH:
1 Cấu trúc chương trình Perl và các kiểu dữ liệu:
1.1 Cấu trúc chương trình Perl:
Một chương trình perl chạy trên Linux thường có cấu trúc sau:
Trang 4#!/usr/bin/perl-wT (Không bắt buộc)
{ Phần khai báo các câu lệnh
}
Với : #!/usr/bin/perl đường dẫn đến chương trình thông dịch Perl trên Linux
wT tham số tuỳ chọn, điều này báo cho trình thông dịch perl cảnh báo những vấn đề
có thể phát sinh với mã kịch bản và trả về lỗi nếu chúng ta sử dụng các dữ liệu phía ngoài
Tương tự, một chương trình Perl là một bó các câu lệnh và định nghĩa Perl đượcđưa 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ắccủ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ôngphải là chương trình shell, nên chúng ta cần một bước phụ: đặt #!/usr/bin/perl làmdòng đầu tiên của tệp 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 phần tử củachương trình là tuỳ chọn, trừ phi hai phần tử của chương trình dính liền với nhau cóthể bị lầm lẫn thành một cái khác, trong trường hợp đó thì khoảng trắng thuộc loạinào đó là bắt buộc (Khoảng trắng bao gồm dấu cách, dấu tab, xuống dòng, về đầudòng hay sang trang mới) 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 đó, nhưng đừng lo, tài liệu sẽ chỉ rõ cho bạn biết là các khoảng trắng phảiđược đặt như thế nào với số lượng bao nhiêu Có thể giả thiết rằng loại và số lượngkhoảng trắng giữa các phần tử trong chương trình là tuỳ ý trong các trường hợpkhác
Mặc dù 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ộtdòng, nhưng một chương trình Perl điển hình được viết xuống dòng và canh lề nhưchương trình C
Cũng giống như một kịch bản shell, chương trình Perl bao gồm tất cả các câu lệnhperl 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áiniệm về hàm chính main như trong C
Trang 5Chú thích của Perl giống như chú thích của kịch bản shell: bất kì cái gì nằm giữamột dấu # tới cuối dòng đều là một chú thích Perl không có chú thích trên nhiềudòng như C.
Không giống hầu hết các shell (nhưng giống như awk và sed), bộ thông dịch Perlphâ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ươngtrình đã bắt đầu chạy, và cũng có nghĩa là khoảng trắng và chú thích sẽ được lược
bỏ 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àybả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 nhấtđơn thuần dựa trên nền tảng là C được coi là trình biên dịch
Việc biên dịch này khá tiêu tốn thời gian Và sẽ là phi hiệu quả nếu một chươngtrình Perl lớn lại chỉ thực hiện một nhiệm vụ nhỏ bé (trong số nhiều nhiệm vụ tiềmnăng) và rồi thoát, vì thời gian chạy cho chương trình sẽ "nhỏ xíu" nếu so với thờigian biên 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ươngtrì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 chiếm không gian đĩa Hiểu theo một cáchnào đó, nó là tốt nhất cho cả hai loại này
1.2 Các kiểu dữ liệu và các thao tác trên dữ liệu
1.2.1 Dữ liệu vô hướng:
Dữ liệu vô hướng là gì?
Vô hướng là loại dữ liệu đơn giản nhất mà Perl thao tác Một vô hướng thì hoặc là một số (giống như 4 hay 3.25e20) hay một xâu các kí tự (giống Xin chào hay Gettysburg Address)
Một giá trị vô hướng có thể được tác động bởi các toán tử (giống như phép cộng hay ghép), và kết quả trả về nói chung là một kết quả vô hướng Một giá trị vô hướng có thể được cất giữ vào trong một biến vô hướng Các biến
vô hướng có thể được đọc từ tệp và thiết bị, và có thể được ghi thiết bị xuất
Trang 6Mặc dầu kiểu vô vô hướng thì hoặc là một số hay một xâu, nhưng cũng vẫn
có ích khi ta nhìn vào các số và xâu tách biệt nhau trong một chốc lát Ta sẽxét số trước rồi đến xâu
Tất cả các số đều có cùng định dạng bên trong
Như bạn sẽ thấy trong vài đoạn tiếp đây, bạn có thể xác định cả số nguyên(toàn bộ số, giống như 14 hay 342) và số dấu phẩy động (số thực với dấuchấm thập phân, như 3.14 hay 1.35*1025) Nhưng bên trong, Perl chỉ tínhvới các giá trị dấu phẩy động độ chính xác gấp đôi Điều này có nghĩa làkhông có giá trị nguyên bên trong Perl - một hằng nguyên trong chươngtrình được xử lí như giá trị dấu phẩy động tương đương Bạn có lẽ không để
ý đến việc chuyển đổi (hay quan tâm nhiều), nhưng bạn nên dừng tìm kiếmphép toán nguyên (xem như ngược với các phép toán dấu phẩy động), vìkhông có phép tính nào như vậy đâu
Hằng kí hiệu động
Hằng kí hiệu là một cách để biểu diễn một giá trị trong văn bản chươngtrình Perl - bạn cũng có thể gọi điều này là một hằng trong chương trìnhmình, nhưng tôi sẽ dùng thuật ngữ hằng kí hiệu Hằng kí hiệu là cách thứcbiểu diễn dữ liệu trong mã chương trình gốc của chương trình bạn như cáivào cho trình biên dịch Perl (dữ liệu được đọc từ hay ghi lên các tệp đềuđược xử lí tương tự, nhưng không đồng nhất)
Perl chấp nhận tập hợp đầy đủ các hằng kí hiệu dấu phẩy động có sẵn chongười lập trình C Số có hay không có dấu chấm thập phân đều được phép(kể cả tiền tố cộng hay trừ tuỳ chọn), cũng như phần chỉ số mũ phụ thêm (kípháp luỹ thừa) với cách viết E Chẳng hạn:
1.25 # một và 1/4
7.25e45 # 7,25 x 1045 (một số dương lớn)
Trang 70377 # 377 hệ tám = 255 trong hệ thập phân
-0xff # âm FF hệ mười = -255 trong hệ thập phân
Xâu là một dãy các kí tự (như Xin chào) Mỗi kí tự đều là một giá trị 8-bit trong toàn bộ tập 256 kí tự (không có gì đặc biệt về kí tự NULL như trong C)
Trang 8trong phạm vi ASCII 32 tới ASCII 126 Tuy nhiên, khả năng để có bất kì kí
tự nào từ 0 tới 255 trong một xâu có nghĩa là bạn có thể tạo ra, 'nhòm' qua,
và thao tác dữ liệu nhị phân thô như các xâu - một cái gì đó mà phần lớn cáctrình tiện ích UNIX khác sẽ gặp khó khăn lớn (chẳng hạn, bạn có thể 'vá lỗi'UNIX bằng việc đọc nó vào trong xâu Perl, tiến hành thay đổi, và ghi lại kếtquả)
Giống như số, xâu có thể biểu diễn hằng kí hiệu (cách thức bạn biểu diễn xâu trong chương trình Perl) Các xâu hằng kí hiệu có theo hai hướng: xâu nháy đơn và xâu nháy kép
Xâu dấu nháy đơn
Xâu dấu nháy đơn là một dẫy các kí tự được bao trong dấu nháy đơn (') Dấu nháy đơn không phải là một phần của bản thân xâu - chúng chỉ có đó
để Perl xác định chỗ bắt đầu và kết thúc của xâu Bất kì kí tự nào nằm giữa các dấu nháy (kể cả dấu xuống dòng, nếu xâu vẫn còn tiếp tục sang dòng sau) đều là hợp pháp bên trong xâu Hai ngoại lệ: để lấy được một dấu nháy đơn trong một xâu có nháy đơn, bạn hãy đặt trước nó một dấu sổ chéo ngược Và để lấy được dấu sổ chéo ngược trong một xâu có nháy đơn, bạn hãy đặt trước dấu sổ chéo ngược nột dấu sổ chéo ngược nữa Ví dụ:
'hello' #năm kí tự: h, e, l, l, o
'dont\'t' #năm kí tự: d, o, n, nháy đơn, t
'' #xâu rỗng (không có kí tự)
'silly\\me' #silly, theo sau là một sổ chéo ngược, sau là me
"hello\n' #hello theo sau là sổ chéo ngược và n
'hello
there' #hello, xuống dòng, there (toàn bộ 11 kí tự)
Trang 9Chú ý rằng \n bên trong môt xâu có nháy đơn thì không được hiểu là dòng mới, nhưng nếu là hai kí tự sổ chéo ngược thì khác (chỉ khi sổ chéo ngược
đi theo sau bởi một sổ chéo ngược khác hay một dấu nháy đơn thì mới mangnghĩa đặc biệt)
Xâu dấu nháy kép
Xâu dấu nháy kép hành động hệt như xâu trong C Một lần nữa, nó lại là dãy các kí tự, mặc dầu lần này được bao bởi dấu ngoặc kép Nhưng bây giờ dấu sổ chéo ngược lấy toàn bộ sức mạnh của nó để xác định các kí tự điều khiển nào đó, hay thậm chí bất kì kí tự nào qua các biểu diễn hệ tám hay hệ mười sáu Đây là một số xâu dấu nháy kép:
"hello world\n" # hello world, và dấu xuống dòng
"new \177" # new, dấu cách và kí tự xoá (177 hệ tám)
"coke\tsprite" # coke, dấu tab, và sprite
Lối thoát sổ chéo:
Dấu sổ chéo có thể đứng trước nhiều kí tự khác nhau để hàm ý những điềukhác nhau (về điển hình nó được gọi là lối thoát sổ chéo) Danh sách đầy đủcủa các lối thoát xâu nháy kép được cho trong Bảng 2-1
Bảng 2-1 Dấu sổ chéo ngược trong xâu nháy kép
Trang 10\a phát 1 tiếng "bíp"
\e escape
\007 ký tự ASCII ở hệ tám (007=bíp)
\0x7f ký tự ASCII ở hệ mười sáu (7f=delete)
\cC ký tự điều khiển (ở đây là Ctrl-C)
\\ dấu sổ chéo ngược
\" dấu nháy kép
\l ký tự tiếp theo sẽ chuyển thành chữ thường
\L tất cả các ký tự tiếp theo cho tới \E sẽ thành chữ thường
\u ký tự tiếp theo sẽ chuyển thành chữ hoa
\U tất cả các ký tự tiếp theo cho tới \E sẽ thành chữ hoa
\E kết thúc \L hay \U
Một tính năng khác của xâu nháy kép là ở chỗ chúng cho phép chen lẫn cácbiến, nghĩa là một số tên biến nào đó bên trong xâu được thay thế bởi giá trịhiện tại của chúng khi xâu được dùng
Các toán tử:
Một toán tử tạo ra một giá trị mới (kết quả) từ một hay nhiều giá trị khác(các toán hạng) Chẳng hạn, + là một toán tử vì nó nhận hai số (toán hạng,như 5 và 6), và tạo ra một giá trị mới (11, kết quả)
Các toán tử và biểu thức của Perl nói chung đều là siêu tập của các toán tử
đã có trong hầu hết các ngôn ngữ lập trình tựa ALGOL/Pascal, như C Mộttoán tử bao giờ cũng trông đợi các toán hạng số hay xâu (hay có thể là tổhợp của cả hai) Nếu bạn cung cấp một toán hạng xâu ở chỗ đang cần tới
Trang 11một số, hay ngược lại, thì Perl sẽ tự động chuyển toán hạng đó bằng việcdùng các qui tắc khá trực giác, mà sẽ được nêu chi tiết trong mục "Chuyểnđổi giữa số và xâu" dưới đây.
Perl cũng hỗ trợ cho toán tử lấy đồng dư mô-đun như trong C Giá trị củabiểu thức 10 % 3 là số dư khi lấy 10 chia cho 3, chính là 1 Cả hai giá trịtrước khi tính toán đều được đưa về giá trị nguyên, cho nên 10.5 % 3.2 đượctính là 10 % 3
Các toán tử so sánh logic là hệt như các toán tử có trong C (< <= == >= > !
=), và việc so sánh hai giá trị về mặt số sẽ cho lại một giá trị đúng (True)hay sai (False) Chẳng hạn, 3 > 2 trả về True vì 3 lớn hơn 2, trong khi 5 != 5
Trang 12trả về False Các định nghĩa về đúng và sai được nói tới về sau, nhưng vớihiện tại, các bạn hãy nghĩ về giá trị cho lại giống như chúng ở trong C - 1 làTrue, còn 0 là False (các toán tử này sẽ được nói lại trong Bảng 2-2).
"hello" "world" # tương tự như "helloworld"
'hello wordl' "\n" # hệt như "hello world\n"
"jerry" " " "tom" # hệt như "jerry tom"
Chú ý rằng việc ghép nối phải được gọi tường minh tới toán tử , khônggiống awk là bạn đơn thuần chỉ việc đặt hai xâu gần nhau
Một tập các toán tử cho xâu khác là toán tử so sánh xâu Các toán tử này đềutựa FORTRAN, như lt thay cho bé hơn Các toán tử so sánh các giá trịASCII của các kí tự của xâu theo cách thông thường
Trang 13Lớn hơn hay bằng >= ge
Bạn có thể tự hỏi tại sao lại có các toán tử phân tách cho số và xâu vậy, nếu
số và xâu được tự động chuyển đổi lẫn cho nhau? Ta hãy xét hai giá trị 7 và
30 Nếu được so sánh như số thì 7 hiển nhiên bé hơn 30, nhưng nếu được sosánh theo xâu, thì xâu "30" sẽ đứng trước xâu "7" (vì giá trị ASCII của 3 thì
bé hơn giá trị ASCII của 7), và do đó là bé hơn Cho nên, không giống awk,Perl đòi hỏi bạn xác định đúng kiểu so sánh, liệu đó là số hay xâu
Chú ý rằng các phép so sánh số và xâu về đại thể ngược với những điều xẩy
ra cho chỉ lệnh test của UNIX, mà thường dùng kí hiệu -eq để so sánh sốcòn = để so sánh xâu
Vẫn còn một toán tử xâu khác là toán tử lặp lại xâu, bao gồm một kí tự chữthường đơn giản x Toán tử này lấy toán hạng trái của nó (một xâu), và thựchiện nhiều việc ghép bản sao của xâu đó theo số lần do toán hạng bên phảichỉ ra (một số) Chẳng hạn:
tự 5555 Chú ý rằng nếu ta đảo ngược trật tự các toán hạng, thì ta sẽ làmnăm bản sao của xâu 4, cho 44444 Điều này chỉ ra rằng việc lặp lại xâu làkhông giao hoán
Số đếm bản sao (toán hạng bên phải) trước hết sẽ bị chặt đi để cho giá trịnguyên (4.8 trở thành 4) trước khi được sử dụng Số đếm bản sao bé hơnmột sẽ gây ra kết quả là xâu rỗng (chiều dài không)
Thứ tự ưu tiên và luật kết hợp của toán tử
Trang 14Thứ tự ưu tiên của toán tử xác định ra cách giải quyết trường hợp không rõràng khi nào dùng toán tử nào trên ba toán hạng Chẳng hạn, trong biểu thức2+3*4, ta sẽ thực hiện phép cộng trước hay phép nhân trước? Nếu ta làmphép cộng trước thì ta sẽ được 5*4, hay 20 Nhưng nếu ta làm phép nhântrước (như ta vẫn được dạ trong toán) thì ta được 2+12, hay 14 Perl chọnđịnh nghĩa toán học thông thường, thực hiện nhân trước Bởi điều này, tanói nhân có số ưu tiên cao hơn cộng.
Bạn có thể phá đi trật tự theo số ưu tiên bằng việc dùng dấu ngoặc Cho nênnếu tôi thực sự muốn cộng trước khi nhân, thì tôi có thể viết (2+3)*4, cho
20 Cũng vậy, nếu tôi muốn biểu thị rằng phép nhân được thực hiện trướcphép cộng, tôi có thể trang điểm thêm, nhưng chẳng để làm gì, một cặp dấungoặc trong 2+(3*4)
Trong khi số ưu tiên là trực giác cho phép cộng và nhân thì ta bắt đầu laovào vấn đề thường hay phải đương đầu với, chẳng hạn, phân biệt thế nào đốivới phép ghép xâu và nâng lên luỹ thừa Cách đúng đắn để giải quyết điềunày là tra cứu sơ đồ số thứ tự ưu tiên toán tử của Perl, được nêu trong Bảng2-3 (chú ý rằng một số các toán tử còn chưa được mô tả) Với những toán tửcũng có trong C, thì những toán tử đó có cùng số thứ tự ưu tiên như chúng
có trong C (mà tôi chẳng bao giờ có thể nhớ được)
Luật kết hợp và số ưu tiên của các toán tử (thấp nhất đến cao nhất)
Trái các toán tử về "danh sách" (mảng)
Trái > (gọi hàm)
- (không xét) ++ (tăng 1) hoặc (giảm 1)
Phải ** (luỹ thừa)
Phải ! ~ \ + - (phủ định lôgic, phủ định bit, tham khảo biến (như pointertrong C), số dương, số âm)
Trái =~ !~ (sánh, không sánh)
Trang 15Trái * / % x (nhân, chia, đồng dư, lặp chuỗi)
Trái + - (cộng, trừ, ghép xâu)
Trái << >> (dịch chuyển bit)
- các toán tử 1 toán hạng (như chomp)
- < > <= >= lt gt le ge
- == != <=> eq ne cmp
Trái & (phép lôgíc 'and' theo bit)
Trái | ^ (phép lôgíc 'or', 'xor' theo bit)
Trái && (phép lôgíc 'and')
Left || (phép lôgíc 'or')
- (toán tử phạm vi), (cấu tử danh sách)
Phải ?: (if-then-else, như trong C)
Phải = += -+ += (các phép gán)
Trái , => (ngăn cách bằng , và bằng =>)
- các toán tử về danh sách (array)
Phải not (phép lôgíc 'not')
Trái and (phép lôgíc 'and')
Trái or xor (phép lôgíc 'or', 'xor')
Trong sơ đồ này, bất kì toán tử đã cho nào đều có số ưu tiên lớn hơn cáctoán tử được liệt kê trên nó, và có số ưu tiên thấp hơn các toán tử được liệt
Trang 16kê dưới nó Các toán tử tại cùng mức ưu tiên được giải quyết theo luật kếthợp.
Giống như với số ưu tiên, luật kết hợp giải quyết trật tự của các phép toánkhi hai toán tử có cùng mức ưu tiên cùng tác động trên ba toán hạng:
2 ** 3 ** 4 # 2 ** (3 ** 4), hay 2 ** 81, hay xấp xỉ 2.41e24
72 / 12 / 3 # (72 / 12) / 3, hay 6 / 3, hay 2
30 / 6 * 3 # (30/6)*3, hay 15
Trong trường hợp thứ nhất, toán tử ** có luật kết hợp phải, cho nên các dấungoặc được áp dụng từ bên phải So sánh với nó, các toán tử * và / có luậtkết hợp trái, cho tập các dấu ngoặc bên trái
Chuyển đổi giữa số và xâu:
Nếu một giá trị xâu được dùng như một toán hạng cho một toán tử số (chẳnghạn, +), thì Perl sẽ tự động chuyển xâu thành giá trị số tương đương, dườngnhư nó đã được đưa vào như một giá trị dấu phẩy động Những chất liệu phi
số đằng đuôi và khoảng trắng đằng đầu đều bị bỏ qua một cách yên lặng và
lễ phép, cho nên " 123.45fred" (với dấu cách đứng trước) chuyển thành123.45 với lời 'nhắc nhở nhẹ nhàng' Tại một cực điểm của điều này, một cái
gì đó không phải là số tẹo nào sẽ được chuyển thành 0 mà không có báotrước (như xâu "jerry" được dùng như số)
Giống vậy, nếu một giá trị số được cho khi đang cần tới một giá trị xâu (chophép ghép xâu chẳng hạn), thì giá trị số sẽ được mở rộng thành bất kì xâunào sẽ được in ra cho số đó Chẳng hạn, nếu bạn muốn ghép nối x và theosau là kết quả của 4 nhân với 5 thì bạn có thể làm đơn giản là: "X".(4*5) sẽthành "X".20, hay "X20" (nhớ rằng các dấu ngoặc này buộc 4*5 phải đượctính trước khi xem xét toán tử ghép nối xâu)
Nói cách khác, bạn không thực sự phải lo lắng gì về liệu bạn có một số haymột xâu (phần lớn thời gian) Perl thực hiện mọi chuyển đổi cho bạn
Trang 17Các toán tử trên biến vô hướng:
Phép toán thông dụng nhất trên biến vô hướng là phép gán, chính là cách đặtmột giá trị cho một biến Toán tử gán của Perl là dấu bằng (giống như C hayFORTRAN), để tên biến bên vế trái và cho giá trị của biểu thức bên vế phải,kiểu như:
$a = 17; # cho $a giá trị 17
$b = $a + 3; # cho $b giá trị hiện tại của $a cộng với 3 (20)
$b = $b * 2; # cho $b giá trị của $b được nhân với 2 (40)
Chú ý rằng dòng cuối dùng biến $b hai lần: khi lấy được giá trị của nó (ở vếphải dấu =), và khi xác định xem phải đặt biểu thức tính được vào đâu (ở vếtrái của dấu =) Điều này là hợp lệ, an toàn và trong thực tế, khá thông dụng.Trong thực tế, nó thông dụng đến mức chúng ta sẽ thấy trong vài phút đây là
ta có thể viết điều này bằng việc dùng cách viết tắt qui ước
Bạn có thể đã chú ý rằng các biến vô hướng bao giờ cũng được tham khảobằng dấu $ đứng trước Trong các kịch bản shell, bạn dùng $ để lấy một giátrị, nhưng để $ đứng một mình để gán một giá trị mới Trong awk hay C,bạn để cho $ đứng riêng hoàn toàn
Việc gán vô hướng có thể được dùng như một giá trị cũng như một phéptoán, như trong C Nói cách khác, $a = 3 có một giá trị, cũng như $a+3 cómột giá trị Giá trị chính là số được gán, cho nên giá trị của $a = 3 là 3 Mặcdầu điều này dường như có vẻ kì lạ lúc thoáng nhìn, việc dùng một phép gánnhư một giá trị lại có ích nếu bạn muốn gán một giá trị trung gian trong mộtbiểu thức cho một biến, hay nếu bạn muốn đơn giản sao cùng một giá trị chomột hay nhiều biến Chẳng hạn:
$b = 4 + ($a = 3); # gán 3 cho $a, rồi cộng kết quả đó với 4 đặt vào $b, được7
$d = ($c = 5); # sao 5 vào $c, và rồi sao vào $d
Trang 18$d = $c = 5; # tương tự như trên, nhưng không có dấu ngoặc
Toán tử gán hai ngôi
Gần như tất cả các toán tử hai ngôi tính một giá trị đều có dạng phép gán haingôi tương ứng với dấu bằng có bổ sung thêm phần tử Chẳng hạn, hai dòngsau đây là tương đương:
$a = $a + 5; # không có toán tử gán hai ngôi
$a += 5; # có toán tử gán hai ngôi
tử ghép nối xâu:
$str = $str " "; # thêm dấu cách vào $str
$str = " "; # cũng điều ấy với toán tử gán
Gần như tất cả các toán tử hai ngôi đều hợp lệ theo cách này Chẳng hạn,toán tử nâng lên luỹ thừa của sẽ được viết là **= Cho nên, $a **= 3 cónghĩa là "nâng một số trong $a lên luỹ thừa ba, rồi đặt kết quả trở lại $a".Giống như toán tử gán đơn, các toán tử này cũng có một giá trị: giá trị mớicủa biến Chẳng hạn:
$a = 3;
$b = ($a += 4); # $a và $b cả hai bây giờ đều là 7
Trang 19Nhưng không may là trật tự tính toán của các toán hạng của toán tử hai ngôilại không được xác định, cho nên một số biểu thức không thể nào được xácđịnh hoàn toàn:
$a = 3;
$b = ($a += 2) * ($a -= 2); # Chương trình tồi: $b có thể là 15 hay 3
Nếu toán hạng bên phải của phép nhân được tính đầu tiên thì kết quả sẽ là 3lần 1, hay 3 Tuy nhiên, nếu toán hạng bên trái được tính trước toán hạngbên phải, thì nó là 5 lần 3, hay 15
$e = ++$d; # $e và $d bây giờ đều là 18
Tại đây, toán tử ++ được dùng như toán tử tiền tố; tức là, toán tử xuất hiện ởbên trái toán hạng của nó Phép tự tăng cũng có thể được dùng trong dạnghậu tố (nằm ở bên phải toán hạng của nó) Trong trường hợp này, kết quảcủa biểu thức này là giá trị của biến trước khi biến được tăng lên Chẳnghạn:
$c = 17;
$d = $c++; # $d là 17, nhưng $c bây giờ là 18
Trang 20Vì giá trị của toán hạng thay đổi nên toán hạng này phải là một biến vôhướng, không phải là biểu thức Bạn không thể nói ++16 để có được 17, màcũng không thể nói ++($a+$b) (là cách nào đó để có được giá trị lớn hơntổng của $a và $b một đơn vị).
Toán tử tự giảm ( ) cũng tương tự như toán tử tự tăng, nhưng trừ đi mộtthay vì cộng với một Giống như toán tử tự tăng, toán tử tự giảm cũng códạng tiền tố và hậu tố Chẳng hạn:
Toán tử chop() và chomp()
Một toán tử khác là chop() Toán tử tiền tố này nhận một đối bên trong cácdấu ngoặc của nó - tên của một biến vô hướng - và bỏ đi kí tự cuối cùng từgiá trị xâu của biến đó Chẳng hạn:
$x = " Xin chào mọi người" ;
chop($x); # $x bây giờ là " Xin chào mọi người"
Lưu ý rằng giá trị của đối bị thay đổi ở đây, do đó cần phải có một biến vôhướng, thay vì chỉ đơn giản là giá trị vô hướng Sẽ là vô nghĩa, chẳng hạn,
để viết chop('suey') để biến nó thành 'sue'’, vì không có chỗ nào để cất giữgiá trị này Bên cạnh đó, bạn có thể chỉ viết 'sue' cũng đủ
Toán tử này trông giống như một lời gọi hàm, và quả thực trả về một giá trị(mà bạn sẽ trông đợi nếu bạn quen thuộc với lời gọi hàm từ các ngôn ngữ).Giá trị được cho lại chính là kí tự đã bị loại bỏ (chữ i trong người ở trên).Điều này có nghĩa là đoạn mã sau đây có lẽ sai:
Trang 21$x = chop($x); # SAI: thay thế $x bằng ksi tự cuối cùng của nó
chop($x); # Đúng: như trên, loại bỏ kí tự cuối
Nếu chop() được cho một xâu rỗng, thì nó chẳng làm gì cả
chomp() tương tự như chop() nhưng nó chỉ xoá nếu ký tự cuối dùng củabiến là ký tự dòng mới mà thôi, nếu là ký tự khác thì nó không làm gì cả.Bạn nên dùng chomp() thay cho chop() khi có thể vì nó an toàn hơn
Xen lẫn vô hướng vào trong xâu
Khi một hằng kí tự xâu là được đặt trong nháy kép thì nó là chủ đề cho việcxen lẫn biến (bên cạnh việc được kiểm tra cho lối thoát sổ chéo ngược).Điều này có nghĩa là xâu này được duyệt qua để tìm các tên biến vô hướng
có thể - có nghĩa là dấu $ đi theo sau một chữ, số hay dấu gạch dưới Khitìm thấy một tham khảo biến thì nó được thay thế bằng giá trị hiện tại (haybất kì xâu rỗng nào nếu biến vô hướng còn chưa được gán giá trị nào).Chẳng hạn:
$a = " jerry" ;
$b = " some text $a" ; # $b bây giờ là " some text jerry"
$c = " no such variable $what" ; # $c là " no such variable "
Để ngăn việc thay thế một biến bằng giá trị của nó, bạn phải hoặc làm thayđổi phần đó của xâu để cho nó xuất hiện trong ngoặc đơn, hoặc đặt trướcdấu $ một dấu sổ chéo ngược:
$jerry = 'hi';
$tom = " a test of " '$jerry'; # hằng kí hiệu: ‘a test of $jerry’
$tom2 = " a test of \$jerry" ; # cũng như vậy
Tên biến sẽ là tên biến dài nhất có thể mà tạo nên nghĩa tại phần đó của xâu.Điều này có thể là vấn đề nếu bạn muốn đặt sau ngay giá trị được thay thế
Trang 22với một văn bản hằng mà bắt đầu bằng một chữ, số hay dấu gạch thấp VìPerl duyệt qua các tên biến nên nó sẽ xét những kí tự là các kí tự tên phụ,
mà không phải là điều bạn muốn Perl cung cấp một định biên cho tên biếntheo các hệ thống tương tự như lớp vỏ Bạn hãy đơn thuần bao tên của biến
đó trong một cặp dấu { và } Hay bạn có thể kết thúc phần đó của xâu và bắtđầu một phần khác của xâu bằng toán tử ghép nối:
$fred = 'pay'; $fredday = " wrong!" ;
$tom = " It’s $fredday" ; # không phải payday, mà là " It’s wrong!"
$tom = " It’s ${fred}day" ; # bây giờ, $tom là " It’s payday!"
$barney2 = " It’s $fred" 'day'; # cách khác để làm việc đó
$barney3 = " It’s " $fred " day" ; # và một cách khác nữa
Toán tử sổ chéo ngược chuyển hoa thường có thể được dùng để làm thayđổi chữ hoa thường được đem theo cùng việc xen lẫn biến Chẳng hạn:
$bigfred = " \Ufred" ; # $bigfred là FRED
$jerry = " fred" ; $bigfred = " \U$jerry" ; # tương tự như trên
$capfred = " \u$jerry" ; # $capfred là " Fred"
$tom = " \LBARNEY" ; # $tom bây giờ là " barney"
$capbarney = " \u\LBARNEY" ; # capbarney bây giờ là
"
Barney"
$bigbarney = " BARNEY" ; $capbarney = " \u\L$bigbarney" ; # như trên
Như bạn có thể thấy, các toán tử dịch chuyển hoa thường được ghi nhớ bêntrong xâu chừng nào chúng còn chưa được dùng tới, cho nên ngay kí tự đầutiên của $capbarney không tuân theo \u, nó vẫn còn là chữ hoa vì \u chưađược dùng đến cho đến khi \L được dùng xong
Trang 23Thuật ngữ xen lẫn biến thường được dùng lẫn với xen lẫn nháy kép, vì cácxâu có nháy kép là chủ đề cho việc xen lẫn biến.
1.2.2 Mảng và danh sách:
Mảng là một danh sách có thứ tự các dữ liệu vô hướng Mỗi phần tử củamảng đều là một biến vô hướng tách biệt với một giá trị vô hướng độc lập.Các giá trị này là được sắp thứ tự - tức là chúng có một trình tự đặc biệt từphần tử thấp nhất đến cao nhất
Mảng có thể có bất kì số phần tử nào Mảng nhỏ nhất không có phần tử nào,trong khi mảng lớn nhất thì có thể lấp kín toàn bộ bộ nhớ có sẵn
Biểu diễn hằng kí hiệu
Một hằng kí hiệu mảng (cách thức bạn biểu diễn giá trị của một mảng bêntrong chương trình) là một danh sách các giá trị tách nhau bằng dấu phẩy vàđược bao trong dấu ngoặc tròn Những giá trị này tạo nên các phần tử củadanh sách Chẳng hạn:
(1,2,3) # mảng gồm ba giá trị 1, 2 và 3
("jerry", 4.5) # hai giá trị, "jerry" và 4.5
Các phần tử của mảng không nhất thiết là hằng - chúng có thể là biểu thức
mà sẽ được tính mới lại mỗi lần mảng được sử dụng Chẳng hạn:
($a, 17) # hai giá trị: giá trị hiện tại của $a, và 17
($b+$c,$d+$e) # hai giá trị
Mảng rỗng (mảng không có phần tử nào) được biểu diễn bằng một cặp dấungoặc rỗng:
() # mảng rỗng (không phần tử)
Một phần tử của mảng có thể bao gồm toán tử cấu thành mảng, được chỉ rabởi hai giá trị vô hướng tách nhau bởi hai dấu chấm liên tiếp ( ) Toán tử
Trang 24này tạo ra một danh sách các giá trị bắt đầu tại giá trị vô hướng bên trái kéocho tới gía trị vô hướng bên phải, mỗi lần tăng lên một Chẳng hạn:
(1 5) # giống như (1, 2, ,3 ,4, 5)
(1.2 5.2) # giống như (1.2, 2.2, 3.2, 4.2, 5.2)
(2 6,10,12) # giống như (2,3,4,5,6,10,12)
($a $b) # phạm vi được xác định bởi giá trị hiện tại của $a và $b
Nếu giá trị vô hướng bên phải bé hơn vô hướng bên trái thì sẽ tạo ra danhsách rỗng - bạn không thể đếm ngược trật tự của các giá trị Nếu giá trị cuốicùng không phải là toàn bộ số bước trên giá trị ban đầu thì danh sách sẽdừng chỉ ngay trước giá trị tiếp mà sẽ vượt ra ngoài phạm vi:
(1.3 6.1) # giống như (1.3, 2.3, 3.3, 4.3, 5.3)
Một cách dùng của hằng kí hiệu mảng là như tham số của toán tử print() đãđược giới thiệu trước đây Các phần tử của danh sách này được in ra màkhông có bất kì khoảng trống xen thêm vào:
print ("Câu trả lời là ", $a, "\n");
Câu lệnh này in ra Câu trả lời là, theo sau bởi một dấu cách, giá trị của $a,
và xuống dòng mới Ta hãy chuyển sang cách dùng khác cho hằng kí hiệumảng
Biến mảng
Một biến mảng giữ một giá trị mảng riêng Các tên biến mảng là tương tựvới các tên biến vô hướng, chỉ khác kí tự khởi đầu, là một dấu @ chứ khôngphải là dấu $ Chẳng hạn:
@jerry # biến mảng @jerry
@A_Very_Long_Array_Variable_Name
Trang 25Lưu ý rằng biến mảng @jerry là không có quan hệ gì theo bất kì cách nàovới biến vô hướng $jerry Perl duy trì không gian tên tách biệt cho các kiểuđối tượng khác nhau
Giá trị của một biến mảng mà chưa được gán là (), danh sách rỗng
Một biểu thức có thể tham khảo tới các biến mảng như một tổng thể, hoặc
nó có thể xem xét và thay đổi từng phần tử của mảng đó
Các hàm và phép toán trên mảng
Các toán tử mảng hành động trên các mảng như một tổng thể Một số toán
tử mảng có thể cho lại một giá trị mảng, mà có thể hoặc được dùng như mộtgiá trị cho toán tử mảng khác, hoặc được gán vào một biến mảng khác
Phép gán
Có lẽ toán tử mảng quan trọng nhất là toán tử gán mảng, cho mảng một giátrị Nó là dấu bằng, giống như toán tử gán vô hướng Perl xác định liệu phépgán có là phép gán vô hướng hay phép gán mảng bằng việc để ý xem liệuphép gán là cho biến vô hướng hay mảng Chẳng hạn:
@jerry = (1,2,3); # mảng jerry nhận ba phần tử 1, 2 và 3
@tom = @jerry; # bây giờ được sao sang @tom
Nếu một giá trị vô hướng được gán vào trong một biến mảng thì giá trị vôhướng trở thành phần tử duy nhất của mảng:
@huh = 1; # 1 được đặt chuyển thành (1) và gán cho @huh
Tên biến mảng có thể xuất hiện trong danh sách hằng kí hiệu mảng Khi giátrị của danh sách được tính thì Perl thay thế tên biến mảng bằng giá trị hiệntại của mảng đó, giống vậy:
@jerry = ("một", "hai");
Trang 26@tom = (4,5,@jerry, 6, 7); # @tom trở thành (4,5,"một","hai",6,7)
@tom = (8, @tom); # đặt 8 vào trước @tom
@tom = (@tom, “cuối”); # và "cuối" vào phía sau @tom
# @tom bây giờ là (8,4,5,"một","hai",6,7,"cuối")
Lưu ý rằng các phần tử mảng được thêm vào đều ở cùng mức như phần cònlại của hằng kí hiệu - một danh sách không thể chứa một danh sách khácnhư một phần tử
Nếu một mảng hằng kí hiệu chỉ chứa các tham khảo biến (không phải làbiểu thức) thì mảng hằng kí hiệu ấy cũng có thể được xử lí như một biến.Nói cách khác, một mảng hằng kí hiệu như thế có thể được dùng ở vế bêntrái của phép gán Mỗi biến vô hướng trong mảng kí hiệu nhận một giá trịtương ứng từ danh sách ở vế phải của phép gán Chẳng hạn:
($a, $b, $c) = (1, 2, 3); # gán 1 cho $a, 2 cho $b, 3 cho $c
($a, $b) = ($b, $a); # tráo đổi $a và $b
($d, @jerry) = ($a, $b, $c); # gán $a cho $d, và ($b,$c) cho @jerry
($e, @jerry) = @jerry; # loại bỏ phần tử thứ nhất của @jerry là $e
# điều này làm cho @jerry = ($c) và $e = $b
Nếu số phần tử được gán không sánh đúng với số các biến để giữ các giá trịthì mọi giá trị vượt quá (vế phải) đều bị loại bỏ, và bất kì biến vượt quá nào(ở vế trái của dấu bằng) đều được cho giá trị undef
Một biến mảng xuất hiện trong danh sách mảng hằng kí hiệu đều phải ởcuối, vì biến mảng nó tiêu thụ tất cả các giá trị còn lại (bạn có thể đặt cácbiến khác sau nó, nhưng chúng sẽ chỉ nhận giá trị undef mà thôi)
Nếu một biến mảng được gán cho một biến vô hướng thì số được gán làchiều dài của mảng, như trong:
Trang 27@jerry = (4, 5, 6); # khởi đầu @jerry mang giá trị (4,5,6)
$a = @jerry; # $a = 3, là số lượng các phần tử có trong @jerry
Chiều dài cũng được cho lại nếu một tên biến mảng được dùng trong hầuhết mọi chỗ mà một giá trị vô hướng đang được cần tới (Trong mục dướiđây có tên "Hoàn cảnh vô hướng mảng", chúng ta sẽ thấy rằng điều này quả
là được gọi như vậy với việc dùng tên mảng trong hoàn cảnh vô hướng).Chẳng hạn, để lấy giá trị bé hơn chiều dài mảng một đơn vị, bạn có thể dùng
@jerry-1, vì toán tử trừ vô hướng cần các vô hướng cho cả hai toán hạngcủa nó Chú ý điều sau:
@jerry = (4, 5, 6); # khởi đầu @jerry mang giá trị (1,2,3)
$a = @jerry; # $a nhận chiều dài của @jerry (là 3)
($a) = @jerry; # $a nhận phần tử đầu tiên của @jerry (là 4)
Phép gán $a = đầu tiên là phép gán vô hướng, và do vậy @jerry được xemnhư một vô hướng, cho lại chiều dài của nó Phép gán thứ hai là phép gánmảng (cho dù chỉ một giá trị là cần tới), và do vậy là phần tử đầu tiên của
@jerry, bỏ đi tất cả phần còn lại
Giá trị của phép gán mảng là chính bản thân giá trị mảng, và có thể đượcxếp tầng như bạn có thể làm với các phép gán vô hướng Chẳng hạn:
@jerry = (@tom = (2,3,4)); # @jerry và @tom mang giá trị (2,3,4)
@jerry = @tom = (2,3,4); # tương tự như trên
Truy cập các phần tử của mảng
Cho tới nay, chúng ta vẫn xử lí mảng như một tổng thể, thêm vào và bỏ bớtcác giá trị bằng việc thực hiện gán mảng Nhiều chương trình có ích đã đượcxây dựng dùng mảng mà thậm chí chẳng truy cập vào phần tử mảng nào.Tuy nhiên, Perl cung cấp toán tử chỉ số truyền thống để tham khảo tới mộtphần tử mảng theo chỉ số Với toán tử chỉ số mảng, các phần tử mảng đều
Trang 28được đánh số bằng việc dùng số nguyên tuần tự, bắt đầu từ không và tănglên một cho mỗi phần tử Phần tử đầu tiên của mảng @jerry mà được truycập tới là $jerry[0] Chú ý rằng @ trên tên mảng trở thành $ trên tham khảophần tử Đó là vì việc tham khảo tới một phần tử của mảng xác định ra mộtbiến vô hướng (một phần của mảng), mà có thể hoặc được gán cho, hoặc cógiá trị hiện tại của nó được dùng trong một biểu thức, kiểu như:
@jerry = (7,8,9);
$b = $jerry[0]; # đặt 7 vào $b (phần tử đầu tiên của @jerry)
$jerry[0] = 5; # bây giờ @jerry = (5,8,9)
Cũng có thể truy cập tới các phần tử khác cũng dễ tương tự, như trong:
$c = $jerry[1]; # gán $jerry[1] vào $s, lúc này $c = 8
$jerry[2]++; # tăng 1 cho phần tử thứ ba của @jerry
$jerry[1] += 4; # cộng 4 vào phần tử thứ hai
($jerry[0], $jerry[1]) = ($jerry[1], $jerry[0]); # tráo đổi hai phần tử đầu của
@jerry
Việc truy cập vào một danh sách các phần tử từ cùng mảng (như trong thí
dụ cuối) được gọi là lát cắt, và thường xuất hiện đến mức có một cách biểudiễn đặc biệt cho nó:
@jerry[0,1] # tương tự như ($jerry[0], $jerry[1])
@jerry[0,1] = @jerry[1,0]; # tráo đổi hai phần tử đầu
@jerry[0,1,2] = @jerry[1,1,1]; # làm cho cả 3 phần tử đầu tiên giống phần
tử thứ hai
@jerry[1,2] = (9,10); # đổi hai giá trị cuối thành 9 và 10
Trang 29Chú ý rằng lát cắt này dùng tiền tố @ chứ không là $ Điều này là vì bạnđang tạo ra một biến mảng bằng việc chọn một phần của mảng chứ khôngphải là biến vô hướng chỉ thâm nhập vào một phần tử.
Lát cắt cũng làm việc trên danh sách hằng kí hiệu, hay bất kì toán tử nào cholại một giá trị danh sách:
@who = ("jerry","tom","chip","dale")[2,3]; # @who = ("chip", "dale")
Các giá trị chỉ số trong những thí dụ này là các số nguyên hằng kí hiệu,nhưng chỉ số cũng có thể là bất kì biểu thức nào cho lại một số, mà rồi đượcdùng để chọn phần tử thích hợp:
@jerry = (7,8,9);
$a = 2;
$b = $jerry[$a]; # $b = $jerry[2], hay giá trị 9
$c = $jerry[$a-1]; # $c nhận $jerry[1], hay 8
($c) = (7,8,9) [$a-1]; # tương tự như trên, nhưng dùng lát cắt
Vậy chương trình Perl có thể có việc thâm nhập mảng tương tự như cácngôn ngữ lập trình truyền thống Ý tưởng này về việc dùng một biểu thứccho chỉ số cũng có tác dụng cho các lát cắt Tuy nhiên bạn hãy nhớ rằng chỉ
số cho lát cắt là một danh sách các giá trị, cho nên biểu thức này là một biểuthức mảng, thay vì là một biểu thức vô hướng
@jerry = (7,8,9); # như trong thí dụ trước
@tom = (2,1,0);
@backfred = @jerry[@tom]; # giống như @jerry[2,1,0], hay ($jerry[2],
$jerry[1],$jerry[0]), hay (9,8,7)
Trang 30Nếu bạn thâm nhập vào một phần tử mảng bên ngoài hai đầu của mảng hiệntại (tức là một chỉ số bé hơn không hay lớn hơn chỉ số của phần tử cuốicùng), thì giá trị undef sẽ được trả về mà không có lời cảnh báo Chẳng hạn:
@jerry = (1,2,3);
$tom = $jerry[7]; # $tom bây giờ là undef
Việc gán một giá trị bên ngoài đầu của mảng hiện tại sẽ tự động mở rộngmảng (cho một giá trị undef cho tất cả các giá trị trung gian, nếu có) Chẳnghạn:
@jerry = (1,2,3);
$jerry[3] = "hi"; # @jerry bây giờ là (1,2,3,"h"”)
$jerry[6] = "ho"; # @jerry bây giờ là (1,2,3,"hi",undef,undef,"ho")
Bạn có thể dùng $#jerry để lấy giá trị chỉ số của phần tử cuối của @jerry(tương tự như trong C-Shell) Bạn thậm chí còn có thể gán vào trong giá trịnày để làm thay đổi chiều dài hiển nhiên của @jerry, làm cho nó to lên hay
co lại, nhưng điều đó nói chung là không cần thiết, vì mảng thường to lênhay co lại một cách tự động
Các toán tử push() và pop()
Một cách dùng thông dụng của mảng là như một chồng thông tin, nơi nhữnggiá trị mới được thêm vào và lấy đi từ phía bên phải của danh sách Nhữngphép toán này thường xuất hiện đến mức chúng có các hàm đặc biệt củariêng chúng:
push(@mylist,$newvalue); # giống @mylist = (@mylist, $newvalue)
$oldvalue = pop(@mylist); # lấy ra phần tử cuối của @mylist
Toán tử pop() trả về undef nếu tham số của nó là một danh sách rỗng
Trang 31Toán tử push() cũng chấp nhận một danh sách các giá trị cần được đẩy vàodanh sách Các giá trị được đẩy vào cuối của danh sách Chẳng hạn:
@mylist = (1,2,3);
push(@mylist,4,5,6); # @mylist = (1,2,3,4,5,6)
Chú ý rằng đối thứ nhất phải là một tên biến mảng - đẩy vào và lấy ra sẽkhông có ý nghĩa với danh sách hằng kí hiệu
Các toán tử shift() và unshift()
Các toán tử push() và pop() làm việc ở bên "phải" của danh sách (phần vớichỉ số cao nhất) Tương tự thế, các toán tử unshift() và shift() thực hiệnnhững hành động tương ứng về bên "trái" của một danh sách (phần với chỉ
số thấp nhất) Sau đây là vài thí dụ:
unshift(@jerry,$a); # như @jerry = ($a,@jerry);
unshift(@jerry,$a,$b,$c); # như @jerry = ($a, $b, $c, @jerry);
$x = shift(@jerry); # như ($x,@jerry) = @jerry;
@jerry = (5,6,7);
unshift(@jerry,2,3,4); # @jerry bây giờ là (2,3,4,5,6,7)
$x = shift(@jerry); # $x nhận 2, $jerry nhận bây giờ là (3,4,5,6,7)
Tương tự như pop(), shift() sẽ trả về undef nếu tham số của nó là một mảngrỗng
Toán tử reverse()
Toán tử reverse() đảo ngược trật tự các phần tử của tham số của nó, cho lạidanh sách kết quả Chẳng hạn:
@a = (7,8,9);
Trang 32@b = reverse(@a); # đặt $b giá trị (9,8,7)
$b = reverse(7,8,9); # tương tự như trên
Chú ý rằng danh sách đối là không bị thay đổi - toán tử reverse() chỉ làmviệc trên bản sao Nếu bạn muốn đảo ngược một mảng "tại chỗ", thì bạn cầngán nó ngược trở lại cho cùng biến:
@b = reverse(@b); # đặt @b là đảo ngược của chính nó
Toán tử sort()
Toán tử sort() nhận một danh sách làm tham số, sắp xếp thứ tự danh sáchtheo thứ tự ASCII và trả về kết quả sau khi đã sắp xếp tăng dần sort()không làm thay đổi danh sách gốc Chẳng hạn:
@x = sort("small", "medium", "large"); # @x nhận "large", "medium",
Toán tử chop() và chomp()
Toán tử chop() và chomp() làm việc trên biến mảng cũng như biến vôhướng Mỗi phần tử của mảng đều có kí tự cuối bị bỏ đi Điều này có thể làthuận tiện khi bạn đọc một danh sách các dòng như các phần tử mảng táchriêng, và bạn muốn bỏ đi dấu dòng mới trong tất cả các dòng ngay lập tức.Chẳng hạn:
Trang 33@stuff = ("hello\n", "world\n", "happy day");
chop(@stuff); # @stuff bây giờ là ("hello", "world", "happy da”)
chomp(@stuff); # @stuff bây giờ là ("hello", "world", "happy day”)
Hoàn cảnh vô hướng và mảng
Như bạn có thể thấy, từng toán tử đều được thết kế để hoạt động trên một số
tổ hợp xác định các vô hướng hay mảng, và cho lại một vô hướng haymảng Nếu một toán tử trông đợi một toán hạng là vô hướng thì ta nói rằngtoán hạng đó là được tính trong hoàn cảnh vô hướng Tương tự, nếu mộttoán hạng đang trông đợi một giá trị mảng thì ta nói rằng toán hạng đó làđược tính trong hoàn cảnh mảng
Điều này là khá thông thường, nhưng đôi khi bạn nhận được một thao táchoàn toàn khác tuỳ theo liệu bạn đang trong hoàn cảnh vô hướng hay mảng.Chẳng hạn, @jerry cho lại nội dung của mảng @jerry trong hoàn cảnhmảng, nhưng cho lại chiều dài của mảng đó trong hoàn cảnh vô hướng.Nhưng sự "huyền ảo" này sẽ được chi chú rõ đối với mỗi toán tử và hàm cụthể
Nếu bạn muốn buộc một biểu thức phải được tính trong hoàn cảnh vô hướngthì bạn có thể ghép nối một xâu rỗng vào cho nó Chẳng hạn:
@a = ('x','y','z');
print ('Tôi thấy ', @a, " phần tử\n"); # sai, sẽ in là "xyz" cho @a
print ('Tôi thấy ', "".@a, " phần tử\n"); # đúng, in 3 cho @a
Tại đây, chúng ta đã nối xâu rỗng "" vào @a, làm nảy sinh xâu "3", rồi trởthành một phần của danh sách cho print
Một giá trị vô hướng được dùng bên trong một hoàn cảnh mảng thì sẽ đượccoi như mảng một phần tử
Trang 34Xen lẫn biến mảng
Giống như các vô hướng, các giá trị mảng có thể được để xen lẫn trong xâu
có nháy kép Một phần tử riêng của một mảng sẽ được thay thế bởi giá trịcủa nó, giống như:
@jerry = ("hello", "dolly");
$y = 2;
$x = "This is $jerry[1]’s place"; # "This is dolly’s place"
$x = "This is $jerry[$y-1]’s place"; # cũng câu ấy
Chú ý rằng biểu thức chỉ số được tính như một biểu thức thông thường,dường như nó ở bên ngoài xâu Nó không phải là biến được xen lẫn trướchết Nói cách khác, nếu $y chứa xâu "2*4" thì ta vẫn nói về phần tử 1, chứkhông phải là 7, vì xâu "2*4" khi chuyển sang số là 2 (vì * ở đây được xemnhư là một ký tự "lạ" chứ không phải là phép nhân
Nếu bạn muốn đặt sau một tham khảo biến vô hướng đơn dấu ngoặc vuôngtrái thì bạn cần định biên cho dấu ngoặc vuông để cho nó không được coinhư một phần của một tham khảo mảng, như sau:
@jerry = ("hello", "dolly"); # đặt giá trị cho @jerry để kiểm thử
$jerry = "right";
# chúng ta đang định nói "this is right[1]"
$x = "this is $jerry[1]"; # sai, $x = "this is dolly"
$x = "this is ${jerry}[1]"; # đúng (được bảo vệ bởi dấu ngoặc nhọn)
$x = "this is $jerry" "[1]"; # đúng (dùng cách ghép xâu)
$x = "this is $jerry\[1]"; # đúng (sổ chéo ngược che dấu nó)
Trang 35Tương tự, một danh sách các giá trị từ một biến mảng cũng có thể được xenlẫn Việc xen lẫn đơn giản nhất là toàn bộ mảng, được chỉ ra bằng việc chotên mảng (kể cả kí tự @ đứng đầu của nó) Trong trường hợp này, các phần
tử được xen lẫn theo trình tự với một dấu cách giữa chúng, như trong:
@jerry = ("a", "bb", "ccc", 1, 2, 3);
$all = "Now for @jerry here!"; # $all = "Now for a bb ccc 1 2 3 here!"
Ta cũng có thể chọn ra một phần của mảng với lát cắt:
@jerry = ("a", "bb", "ccc", 1,2,3);
$all = "Now for @jerry[2,3] here!"; # $all = "Now for ccc 1 here!"
$all = "Now for @jerry[@jerry[4,5]] here!"; # cũng thế
Chúng ta có thể dùng nháy kép nào nếu ta muốn đặt sau một tham khảo tênmảng bằng một hằng kí hiệu dấu ngoặc nhọn trái thay vì một biểu thức chỉsố
1.2.3 Mảng băm
Mảng băm cũng tựa như mảng (kiểu danh sách), trong đó nó là một tập các
dữ liệu vô hướng, với các phần tử riêng được chọn ra bằng một giá trị chỉ sốnào đó Không giống mảng danh sách, giá trị chỉ số của mảng băm khôngphải là số nguyên không âm nhỏ, mà thay vào đó là vô hướng tuỳ ý Những
vô hướng này (còn gọi là khoá) được dùng về sau để tìm kiếm các giá trị từmảng này
Các phần tử của mảng băm không có thứ tự đặc biệt Bạn hãy xem chúngtựa như bàn đầy những quân bài Nửa trên của các con bài là khoá, còn nửadưới là giá trị của chúng Mỗi lần bạn đặt một giá trị vào trong mảng bămthì một con bài mới lại được tạo ra Về sau khi bạn muốn sửa đổi giá trị này,bạn cho khoá, còn Perl tìm ra đúng con bài Cho nên, thực sự, trật tự của cáccon bài là không quan trọng Trong thực tế, Perl cất giữ các con bài (cặpkhoá-giá trị) bên trong theo một thứ tự đặc biệt để dễ dàng tìm ra một con
Trang 36bài cụ thể, cho nên Perl không phải duyệt qua tất cả các cặp để tìm ra đúngcon bài Bạn không thể kiểm soát được trật tự này.
Biến mảng băm
Tên biến mảng băm mà một dấu phần trăm (%) theo sau bởi một chữ cái,theo sau nữa là không hay nhiều chữ, chữ số và dấu gạch dưới Nói cáchkhác, phần đi sau dấu % giống hệt cái mà chúng ta có cho tên biến vô hướng
và biến mảng Và tương tự, chẳng có quan hệ gì giữa $jerry, @jerry và
Giống như với mảng danh sách, bạn có thể tạo ra những phần tử mới chomảng băm bằng việc gán cho mảng một phần tử:
$jerry{"aaa"} = "bbb"; # tạo ra khoá "aaa" với giá trị "bbb"
$jerry{234.5} = 456.7; # tạo ra khoá "234.5", giá trị 456.7
Hai câu lệnh này tạo ra hai phần tử trong mảng Những tham khảo về sau tớicùng những phần tử này (dùng cùng khoá) sẽ cho lại giá trị được cất giữ
print $jerry{"aaa"}; # in "bbb"
$jerry{234.5} += 3; # $jerry{234.5} giờ mang giá trị 459.7
Việc tham khảo tới một phần tử không có sẵn sẽ trả về giá trị undef, giốngnhư với mảng danh sách hay biến vô hướng không xác định
Biểu diễn hằng kí hiệu cho mảng băm