Tải bản đầy đủ (.doc) (72 trang)

Phân tích Cấu trúc chương trình Perl, các kiểu dữ liệu và các thao tác trên dữ liệu

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 (301.1 KB, 72 trang )

PHÂN CÔNG NHIỆM VỤ:
Nhóm 3
TH
ĐINH THẾ DUY 3
25/03/09
ĐINH HUY TƯỞNG 3
1
NGUYỄN THỊ XUÂN 3
VŨ QUỐC HUY 3
2
NGUYỄN THỊ HÀ 3
ĐINH VĂN HÙNG 3
3
NGUYỄN THỊ GẤM 3
TRỊNH THỊ HUYỀN TRANG 3
4
VŨ VĂN PHONG 3
VŨ NGỌC TRƯỜNG 3
5
NGUYỄN VĂN TIẾN 3
PHẠM THỊ HƯƠNG LAN 3
6
TẠ NGỌC NGUYÊN 3
PHẠM THANH TÙNG 3
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
4: Các lệnh vào/ra tệp
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


I. PHẦN MỞ ĐẦU:
1. Giới thiệu
2. Lịch sử phát triển
II. PHÂN TÍCH:
1. Cấu trúc chương trình Perl, các kiểu dữ liệu và các thao tác trên dữ liệu
2. Các lệnh vào/ra dữ liệu
3. Các lệnh vào/ra tệp
4. 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
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ể được đọc từ tệp và thiết bị, và có thể được ghi thiết bị xuất.
Số:
Mặ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ấu
chấm thập phân, như 3.14 hay 1.35*1025). Nhưng bên trong, Perl chỉ tính
vớ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ương
trì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ếm
phé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ương
trình Perl - bạn cũng có thể gọi điều này là một hằng trong chương trình
mì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ức
biểu diễn dữ liệu trong mã chương trình gốc của chương trình bạn như cái
và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 cho
ngườ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)
-6.5e24 # -6,5 x 1024 (một số âm lớn)
-12e-24 # -12 x 10-24 (một số âm rất nhỏ)
-1.2E-23 # tương tự như số ở trên: -1,2 x 10-23
Hằng kí hiệu nguyên
Các hằng kí hiện nguyên cũng được ghi trực tiếp, ví dụ:
12
15
-2004
3485
Chú ý: Perl hỗ trợ cho hằng kí hiệu hệ cơ số tám và hệ mười sáu (hệt như
kiểu C). Số hệ tám bắt đầu bằng số 0 đứng đầu, còn số hệ mười sáu thì bắt
đầu bằng 0x hay 0X. Các chữ số hệ mười sáu từ A đến F (trong cả hai kiểu
chữ hoa thường) đều biểu thị cho các giá trị số qui ước từ 10 đến 15. Chẳng
hạn:
0377 # 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).
Xâu:
Xâu ngắn nhất có thể được là xâu rỗng-không có kí tự nào. Xâu dài nhất thì
chiếm trọn bộ nhớ máy tính (mặc dầu bạn sẽ chẳng thể nào làm gì nhiều với
nó cả). Điều này phù hợp với nguyên lí "không có giới" mà Perl cung cấp

cho bạn. Các xâu điển hình là các dẫy in được gồm các chữ, số và dấu ngắt
trong 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ác
trì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ết
quả).
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ự)
Chú ý 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 mang
nghĩ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ều
khá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
Kết cấu Ý nghĩa
\n xuống dòng mới
\r về đầu dòng
\t ký tự tab
\f báo hết trang
\b xoá lui 1 ký tự
\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ác
biế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ột
toá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
một số, hay ngược lại, thì Perl sẽ tự động chuyển toán hạng đó bằng việc
dù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.
Toán tử cho số
Perl cung cấp các toán tử cộng, trừ, nhân, chia điển hình thông thường.
Chẳng hạn:
2 + 3 # 2 cộng 3, = 5
5.1 - 2.4 # 5.1 trừ 2.4, = 2.7
3 * 12 # 3 lần 12, = 36
14 / 2 # 14 chia cho 2, = 7
10.2 / 0.3 # 10.2 chia cho 0.3, = 34
10 / 3 # 10 chia cho 3, bao giờ cũng là phép chia dấu phẩy động, nên =
3.333
Bên cạnh đó, Perl cung cấp toán tử lũy thừa kiểu FORTRAN, mà nhiều
người đã từng mong mỏi cho Pascal và C. Toán tử này được biểu diễn bằng
hai dấu sao, như 2**3 = 23 = 8. (nếu kết quả không thể khớp trong số dấu
phẩy động độ chính xác gấp đôi, như một số âm mà lại luỹ thừa theo số

không nguyên, hay một số lớn lấy luỹ thừa theo số lớn, thì bạn sẽ nhận được
lỗi 'định mệnh' - fatal error).
Perl cũng hỗ trợ cho toán tử lấy đồng dư mô-đun như trong C. Giá trị của
biể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 được
tí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
trả về False. Các định nghĩa về đúng và sai được nói tới về sau, nhưng với
hiệ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).
Toán tử xâu
Các giá trị xâu có thể được ghép với toán tử chấm (.) (đó là dấu chấm đơn).
Điều này không làm thay đổi xâu, cũng như 2+3 không làm thay đổi 2 hay
3. Nhưng kết quả trả về là một xâu ghép (theo thứ tự) của 2 xâu thành phần,
vậy là có sẵn cho tính toán thêm hay được cất giữ trong một biến:
"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ông
giố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 đều
tự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.
Các toán tử so sánh số và xâu
Phép so sánh Số Xâu
Bằng == eq
Không bằng != ne
Bé hơn < lt

Lớn hơn > gt
Bé hơn hay bằng <= le
Lớ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 so
sá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ực
hiệ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ải
chỉ ra (một số). Chẳng hạn:
"jerry" x 3 # là "jerryjerryjerry"
"tom" x (4+1) # là "tom" x 5 hay "tomtomtomtomtom"
(3+2) x 4 # là 5 x 4, hay thực sự là "5" x 4, là "5555"
Nhưng toán tử lặp lại xâu cần một xâu cho toán hạng bên trái, cho nên số 5
được chuyển thành xâu "5" (dùng các qui tắc sẽ được mô tả chi tiết về sau),
thành xâu một kí tự. Xâu mới này rồi được sao lên bốn lần, cho xâu bốn kí
tự 5555. Chú ý rằng nếu ta đảo ngược trật tự các toán hạng, thì ta sẽ làm
nă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ơn
mộ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ử
Thứ 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ức
2+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àm
phép cộng trước thì ta sẽ được 5*4, hay 20. Nhưng nếu ta làm phép nhân
trướ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, ta
nó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ên
nế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ước
phép cộng, tôi có thể trang điểm thêm, nhưng chẳng để làm gì, một cặp dấu
ngoặ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 lao
vào vấn đề thường hay phải đương đầu với, chẳng hạn, phân biệt thế nào đối
với phép ghép xâu và nâng lên luỹ thừa. Cách đúng đắn để giải quyết điều
này là tra cứu sơ đồ số thứ tự ưu tiên toán tử của Perl, được nêu trong Bảng
2-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ư pointer
trong C), số dương, số âm)
Trái =~ !~ (sánh, không sánh)
Trá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ác
toá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
kê 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ết
hợ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án
khi 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ấu
ngoặc được áp dụng từ bên phải. So sánh với nó, các toán tử * và / có luật
kế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ẳng
hạn, +), thì Perl sẽ tự động chuyển xâu thành giá trị số tương đương, dường
như 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ành
123.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áo
trướ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 (cho
phép ghép xâu chẳng hạn), thì giá trị số sẽ được mở rộng thành bất kì xâu
nào sẽ được in ra cho số đó. Chẳng hạn, nếu bạn muốn ghép nối x và theo
sau 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 được
tí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ố hay
một xâu (phần lớn thời gian). Perl thực hiện mọi chuyển đổi cho bạn.
Cá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 đặt
mộ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 hay
FORTRAN), để 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ảo
bằ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ép
toá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ặc
dầ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án
như một giá trị lại có ích nếu bạn muốn gán một giá trị trung gian trong một
biể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ị cho
mộ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, được
7
$d = ($c = 5); # sao 5 vào $c, và rồi sao vào $d
$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 hai
ngôi tương ứng với dấu bằng có bổ sung thêm phần tử. Chẳng hạn, hai dòng
sau đâ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
Và tương tự như thế:
$b = $b * 3;
$b *= 3;
Trong từng trường hợp, toán tử này làm cho giá trị hiện tại của biến được
thay đổi theo một cách nào đó, thay vì đơn giản ghi đè lên giá trị này bằng
kết quả của một biểu thức mới nào đó. Toán tử gán thông dụng khác là toán
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ới

của biến. Chẳng hạn:
$a = 3;
$b = ($a += 4); # $a và $b cả hai bây giờ đều là 7
Như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ôi
lạ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à 3
lầ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ạng
bên phải, thì nó là 5 lần 3, hay 15.
Tự tăng và tự giảm
Dường như cũng đã đủ dễ dàng để thêm 1 vào $a bằng việc nói $a += 1.
Perl còn đi xa hơn và thậm chí lại còn làm ngắn hơn cho điều này nữa. Toán
tử ++ (được gọi là toán tử tự tăng) cộng thêm một vào toán hạng của nó, và
cho lại giá trị đã được tăng, giống như:
$a += 1; # dùng toán tử gán
++$a; # dùng tự tăng tiền tố
$d = 17;
$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ạng
hậ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ẳng
hạn:
$c = 17;
$d = $c++; # $d là 17, nhưng $c bây giờ là 18
Vì 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ơn

tổ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ột
thay 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:
$x = 12;
$x; # $x bây giờ là 11
$y = $x ; # $y là 11, còn $x bây giờ là 10
Không giống C, các toán tử tự tăng và tự giảm làm việc trên số dấu phẩy
động. Cho nên việc tăng một biến với giá trị 4.2 sẽ cho 5.2 như dự kiế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ác
dấ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:
$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ủa
biế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ệc
xen 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. Khi
tìm thấy một tham khảo biến thì nó được thay thế bằng giá trị hiện tại (hay
bấ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ước
dấ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ế
vớ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ến
theo 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ên
trong xâu chừng nào chúng còn chưa được dùng tới, cho nên ngay kí tự đầu
tiê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.
Thuậ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ác
xâ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ủa
mả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ên
trong 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ủa
danh 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ấu
ngoặ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ỉ ra
bởi hai giá trị vô hướng tách nhau bởi hai dấu chấm liên tiếp ( ). Toán tử
nà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éo
cho 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 danh
sá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ối
cù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ệu
mả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ông
phải là dấu $. Chẳng hạn:

@jerry # biến mảng @jerry
@A_Very_Long_Array_Variable_Name
@A_Very_Long_Array_Variable_Name_that_is_different
Lưu ý rằng biến mảng @jerry là không có quan hệ gì theo bất kì cách nào
vớ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ột
giá 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ép
gán có là phép gán vô hướng hay phép gán mảng bằng việc để ý xem liệu
phé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ện
tại của mảng đó, giống vậy:
@jerry = ("một", "hai");

×