Tải bản đầy đủ (.pdf) (80 trang)

LẬP TRÌNH TRONG MÔI TRƯỜNG SHELL

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 (811.17 KB, 80 trang )

LINUX, Lp trình shell
________________________________________________________________________


1
UNIX/Linux

LP TRÌNH TRONG MÔI TRNG SHELL

1. Shell ca UNIX/LINUX

2. S DNG SHELL NH NGÔN NG LP TRÌNH
2.1. iu khin shell t dòng lnh
2.2. iu khin shell bng tp tin kch bn (script file)
2.3. Thc thi script

3. CÚ PHÁP NGÔN NG SHELL
3.1. S dng bin
3.1.1. Các kí t đc bit (Metalcharacters ca Shell)
3.1.1.1 Chuyn hng vào/ra
3.1.1.2 Các kí t đc bit kim soát tin trình
1.& (Ampersand)
2.Ngoc đn ( ; )
3. Du nháy ` ` (backquotes)
4.ng dn (Pipelines)
3.1.1.3 Du bc chui (quoting)
1.Backslash (\)
3.1.2. Biên môi trng (environment variable)
3.1.3. Bin tham s (parameter variable)
3.2. iu kin
3.2.1. Lnh test hoc [ ]


3.3. Cu trúc điu khin
3.3.1. Lnh if
3.3.2. Lnh elif
3.3.3. Vn đ phát sinh vi các bin
3.3.4. Lnh for
3.3.5. Lnh while
3.3.6. Lnh intil
3.3.7. Lnh case
3.4. Danh shell thc thi lnh (Lists)
3.4.1. Danh sách AND (&&)
3.4.2 Danh sáchl OR ( || )
3.4.3. Khi lnh
3.5. Hàm (function)
3.5.1 Bin cc b
 và bên toàn cc
3.5.2. Hàm và cách truyn tham s
3.6. Các lnh ni ti ca shell
3.6.1. break
3.6.2 continue
________________________________________________________________________
Hunh Thúc Cc, Vin CNTT tp hp và biên son
LINUX, Lp trình shell
________________________________________________________________________


2
3.6.3. Lnh : (lnh rng)
3.6.4. Lnh . (thc thi)
3.6.5. eval
3.6.6. exec

3.6.7. exit n
3.6.8. export
3.6.9 Lnh expr
3.6.10. printf
3.6.11 return
3.6.12 set
3.6.13. shift
3.6.14. trap
3.6.15. unset
3.7. Ly v kt qu ca mt lnh
3.7.1. c lng toán hc
3.7.2. M rng tham s
3.8. Tài liu Here

4. DÒ LI (DEBUG) CA SCRIPT

5. HIN TH MÀU SC (COLOR)
5.1. Màu ch
5.2. Thuc tính vn bn
5.3. Màu nn

6. XÂY DNG NG DNG BNG NGÔN NG SCRIPT
6.1. Phn tích yêu cu
6.2. Thit k ng dng

7. KT CHNG
8. MT S TÓM TT
8.1 To và chy các chng trình shell
8.1.1 To mt chng trình shell
8.1.2 Chy chng trình shell

8.2 S dng bin
8.2.1 Gán mt giá tr cho bin
8.2.2 Truy nhp giá tr ca mt bin
8.2.3 Tham s v
 trí và bin xây dng sn trong shell
8.2.4 Ký t đc bit và cách thoát khi ký t đc bit
8.2.5 Lnh test
8.3 Các hàm shell
8.3.2 Các ví d to hàm
8.4 Các mnh đ điu kin
8.4.1 Mnh đ if
8.4.2 Mnh đ case
________________________________________________________________________
Hunh Thúc Cc, Vin CNTT tp hp và biên son
LINUX, Lp trình shell
________________________________________________________________________


3
8.5 Các mnh đ vòng lp
8.5.1 Mnh đ for
8.5.2 Mnh đ while
8.5.3 Mnh đ until
8.5.4 Câu lnh shift

TÀI LIU THAM KHO









































________________________________________________________________________
Hunh Thúc Cc, Vin CNTT tp hp và biên son
LINUX, Lp trình shell
________________________________________________________________________


4

Trc khi bt tay vào vit nhng ng dng không cn ti các ngôn ng lp trình
phc tp khác, chng này s đ cp cách tip cn vi ngôn ng kch bn (script) ca h
v (shell, t đây s gi là shell script), dùng điu khin và tng tác vi Linux. Khi tip
cn vi DOS, DOS cung cp mt shell đ to các x lí theo lô trên nhng tp tin *.bat,
tng đi rõ ràng, đn gin. Tuy nhiên shell ca DOS không mnh và hu dng bng
shell script trên Linux. Tài liu này s cung cp nhng kin thc va đ đ ngi dùng
UNIX/LINUX có th dùng shell to ra các chng trình thc thi hu hiu, thm chí còn
có th dùng shell đ thc hin đc mi thao tác kim soát h điu hành (nh các nhà
chuyên nghip vn nói). Nhng đích chính cn đt đc nh sau:
1.Shell và mc đích s dng
2.Cú pháp và cách điu khin các lnh ca ngôn ng shell
3.Hin th và th hin màu sc
4.các ví d thc hành

1. Shell ca UNIX/Linux

Mi th đc thc hin trên Unix đu bi tin trình. Vy to ra tin trình nh th nào ?

Cách th nht là vit ra các chng trình mà các chng trình này bit cách to ra tin
trình (C/C++). Tuy nhiên cách này đòi hi nhiu hiu bit và n lc. Cng nh các h
điu hành làm vic kiu o khác, Unix h tr mt phng tin x lí lnh làm giao din
gia lnh máy (mà ngi dùng đa vào) và vic thc thi ca lnh đó (bi Unix). Phng
tin đó gi là shell. T khi ra đi Unix đã có vài kiu shell, đó là Bourne, C, Korn shell.
Thc ra shell làm gì ? Tòan b mc đích ca shell là đ khi đng các tin trình x lí
lnh đa vào: yêu cu đa (dòng) lnh vào, đc đu vào, thông dch dòng lnh đó, và to
ra tin trình đ thc hin lnh đó. Nói cách khác shell quét dòng lnh đa vào máy tính,
cu hình môi trng thc thi và to tin trình đ thc hin lnh.


Hình 2: V trí ca shell khi “thc hin” lnh ca ngi dùng Shell dch các
lnh nhp vào thành li gi h thng, chuyn các ký hiu dn hng >, >>
hay | thành d liu di chuyn gia các lnh. c các bin môi trng đ
tìm ra thông tin thc thi lnh.
Nh vy tìm hiu shell thc t là hc mt ngôn ng lp trình, cho dù không phc
tp nh C, hay các ngôn ng khác, nhng cng phi qua nhng đòi hi cn thit. Trong
Unix/Linux có các lai shell khác nhau và có th la chn đ dùng theo nhu cu mà
ngi dùng thy phù hp. Hình 2 là mô hình tng tác gia các shell, chng trình ng
dng, h X-Window và ht nhân.
________________________________________________________________________
Hunh Thúc Cc, Vin CNTT tp hp và biên son
LINUX, Lp trình shell
________________________________________________________________________


5


Cac ung

dung
C shell (csh)
Bourne
Again shell
(bash)
X-Wimdows
shell
Nhan
HDH


Hình 2

Linux/Unix tách bit các ng dng, lnh gi các hàm chc nng ca nhân thành
nhng đn th rt nh (tin trình). Tuy nhiên, nhiu lnh ca Linux có th kt hp li vi
nhau đ to nên chc nng tng hp rt mnh m. Ví d:
$ ls -al | more
lnh trên đc kt hp bng hai lnh, ls lit kê toàn b danh sách tp và th mc trên đa
ra màn hình, nu danh sách quá dài, ls chuyn d liu kt xut cho lnh more x lý hin
th kt qu thành tng trang màn hình. Linux có cách kt hp d liu kt xut ca các
lnh vi nhau thông qua c ch chuyn tip (redirect), ng dn (pipe).
Kt hp các lnh vi nhau ch bng dòng lnh không cha đ. Nu mun t hp
nhiu lnh đng thi vi nhau và tùy vào tng điu kin, kt xut ca lnh, mà có nhng
ng x thích hp thì sao? Lúc đó s dùng đn các cu trúc lp trình r nhánh nh if, case.
Trng hp bn mun thc hin các thao tác vòng lp, phi dùng các lnh nh for, while
Shell chính là trình din dch cung cp cho ngi dùng kh nng này. Hu ht các
Shell trong Unix/Linux s dng mt ngôn ng gn ging vi C (điu này cng d hiu
bi trong th gii Unix/Linux, C là ngôn ng lp trình thng tr). Ngôn ng Shell càng
ging C thì lp trình viên hay ngi điu khin Linux càng cm thy thân thin vi HH.


H thng cung cp cho ngi dùng rt nhiu chng trình shell. Mi shell có mt
s tin ích nh h tr ch đ gõ phím, ghi nh lnh. Kt hp các tin ích ca shell đ to
ra mt chng trình chy đc, thì mt chng trình nh vy đc lu di dng mt
tp, gi là tp kch bn (script, hãy th m mt tp nh vy và quan sát cu trúc ca tp).
Vit đc mt tp script, thc cht là đã lp trình theo shell. Mt khi đã quen thuc vi
mt shell và cách hot đng ca shell đó, ngi dùng có th làm ch đc các shell khác
mt cách đ dàng.

Các shell trên Unix/Linux:

sh ( Bourne ) shell nguyên thy áp dng cho Unix
Csh, tcsh và zsh dòng shell s d
ng cu trúc lnh ca C làm ngôn ng kch bn.
c to ra đu tiên bi Bia Joy. Là shell thông dng th hai sau
bash shell.
________________________________________________________________________
Hunh Thúc Cc, Vin CNTT tp hp và biên son
LINUX, Lp trình shell
________________________________________________________________________


6
bash shell ch yu ca Linux. Ra đi t d án GNU. bash (Vit tt ca
Bourne Again Shell có li đim là mã ngun đc công b rng
rãi. Nu bash cha có sn trong h thng Unix hay Linux, hãy ti
v, biên dch và s dng min phí ti đa ch www.gnu.org
rc shell mô rng ca csh vi nhiu tng thích vi ngôn ng C hn.
rc cng ra đi t d án GNU.

Shell chun thng đc các nhà phân phi Linux s dng hin nay là bash shell. Khi cài

đt Linux, trình cài đt thng mc đnh bash là shell khi đng. Có th tìm thy chng
trình shell này trong th mc /bin vi tên chng trình là bash. bash đôi khi là mt
chng trình nh phân đôi khi là mt script gi đn liên kt nh phân khác. Có th dùng
lnh file đ xem bash là mt tp tin nh phân hay script nh sau:
$ file /bin/bash
/bin/bash: ELF 32-bit LSB executable. Intel 80386
nu kt qu kt xut là dng ELF thì có ngha là bash là chng trình nh phân.
Tuy bash là shell s dng ph bin trong Linux, nhng các ví d v lp trình s s
dng ngôn ng và lnh ca shell sh bi vì sh là shell nguyên thy, có th chy trên c
Unix. Bng lnh file ta s thy trong hu ht các bn Linux hin nay sh ch là liên kt đn
bash mà thôi. Ví d:
$ file /bin/sh
/bin/sh: symbolic link to bash
điu này có ngha là bash hoàn toàn có th din dch và điu khin các lnh ca shell sh.

2. S DNG SHELL NH NGÔN NG LP TRÌNH

Có hai cách đ vit chng trình điu khin shell: gõ chng trình ngay t dòng
lnh là cách đn gin nht. Tuy nhiên mt khi đã thành tho có th gp các lnh vào mt
tp đ chy (chúng tng đng vi cách DOS gi tp *.bat), điu này hiu qu và tn
dng trit đ tính nng t đng hóa ca shell.

2.1. iu khin shell t dòng lnh

Chúng ta hãy bt đu, giá s trên đa cng có rt nhiu file ngun .c, bn mun
truy tìm và hin th ni dung ca các tp ngun cha chui main(). Thay vì dùng lnh
grep đ tìm ra tng file sau đó quay li dùng lnh more đ hin th file, ta có th dùng
lnh điu khin shell t đng nh sau:
$ for file in *
do

if grep -l 'main( ) ' $file
then
more $fle
fi
done
Khi gõ mt lnh cha hoàn chnh t du nhc ca shell, shell s chuyn du nh
c thành
>, shell ch nhp đy đ các lnh trc khi thc hin tip. Shell t trng hiu đc khi
nào thì lnh bt đu và kt thúc. Trong ví d trên lnh for . . . do s kt thúc bng done.
________________________________________________________________________
Hunh Thúc Cc, Vin CNTT tp hp và biên son
LINUX, Lp trình shell
________________________________________________________________________


7
Khi gõ xong done, shell s bt đu thc thi tt c nhng gì đã gõ vào bt đu t for. 
đây, file là mt bin ca shell, trong khi * là mt tp hp đi din cho các tên tp tìm thy
trong th mc hin hành.
Bt tin ca vic điu khin ngôn ng shell t dòng lnh là khó ly li khi lnh
trc đó đ sa đi và thc thi mt ln na. Nu ta nhn phím Up/Down thì shell có th
tr li khi lnh nh sau:
$ for file in * ; do ; if grep -1 'main( )’ $file;
then ; more $file; fi; done
ây là cách các shell Linux vn thng làm đ cho phép thc thi nhiu lnh cùng lúc
ngay trên dòng lnh. Các lnh có th cách nhau bng du (;). Ví d:
$ mkdir myfolđer; cd myfolder;
s to th mc myfolder bng lnh mkdir sau đó chuyn vào th mc này bng lnh cd.
Ch cn gõ Enter mt ln duy nht đ thc thi hai lnh cùng lúc. Tuy nhiên sa cha các
khi lnh nh vy không d dàng và rt d gây li. Chúng ch thun tin cho kt hp

khong vài ba lnh.  d bo trì bn có th đa các lnh vào mt tp tin và yêu cu shell
đc ni dung tp tin đ thc thi lnh. Nhng tp tin nh vy gi là tp tin kch bn (shell
script).

2.2. iu khin shell bng tp tin kch bn (script file)

Trc ht bn dùng lnh
$cat > first.sh hay các trình son tho nh vi hay emacs (hoc mc) đ son ni
dung tp tin first.sh nh sau:
# ! /bin/ sh
# first.sh
# Script nay se tìm trong th mc hin hành các chui
# mang ni dung main( ) , ni dung ca fìle s đc hin th ra màn hình nu tìm
thy.
for file in *
do
if grep -l 'main( ) ' $file
then
more $fle
fi
done

exit 0
Không nh chú thích ca C, mt dòng chú thích (comment) trong ngôn ng shell bt đu
bng ký t #. Tuy nhiên 
đây có mt chú thích hi đc bit đó là #!/bin/sh. y thc s
không phi là chú thích. Cp ký t #! là ch th yêu cu shell hin ti triu gi shell sh
nm trong th mc /bin. Shell sh s chu trách nhim thông dch các lnh nm trong tp
tin script đc to.


Có th ch đnh #!/bin/bash làm shell thông dch thay cho sh, vì trong Linux tht ra
sh và bash là mt. Tuy nhiên nh đã nêu, trên các h Unix vn s dng shell sh làm
chun, vì vy vn là mt thói quen tt cho lp trình viên nu s dng shell sh. Khi
________________________________________________________________________
Hunh Thúc Cc, Vin CNTT tp hp và biên son
LINUX, Lp trình shell
________________________________________________________________________


8
tip cn vi UNIX, ta s cm thy quen và thân thuc vi shell này hn. Nên chy
script trong mt shell ph (nh gi sh chng hn), khi đó mi thay đi v môi
trng mà script gây ra không nh hng đn môi trng làm vic chính.

Ch th #! Còn đc dùng đ gi bt kì chng trình nào ta mun chy trc khi script
tip theo đc dch. Lnh exit bo đm rng script sau khi thc thi s tr v mã li, đây là
cách mà hu ht các chng trình nên làm, mc dù mã li tr v ít khi đc dùng đn
trong trng hp thc hin tng tác trc tip t dòng lnh. Tuy nhiên, nhn bit mã tr
v ca mt đon script sau khi thc thi, li thng rt có ích nu bn triu gi script t
trong mt script khác. Trong đon chng trình trên, lnh exit s tr v 0, cho bit script
thc thi thành công và thoát khi shell gi nó. Mc dù khi đã lu tp tin script vi tên .sh,
nhng UNIX và Linux không bt buc điu này. Him khi Linux s dng phn đuôi m
rng ca tp tin làm du hiu nhn dng, do đó tp tp script có th là tùy ý. Tuy vy .sh
vn là cách chúng ta nhn ngay ra mt tp tin có th là script ca shell mt cách nhanh
chóng.

2.3. Thc thi script

Chúng ta va to ra tp tin script first.sh, nó có th đc gi thc thi theo 2 cách.
Cách đn gin nht là triu gi trình shell vi tên tp tin script làm đi s. Ví d:

$ /bin/ sh first.sh
Cách gi trên là bình thng, nhng vn quen thuc hn nu ta có th gi first.sh ngay t
dòng lnh, tng t các lnh Linux thông thng.  làm đc điu này, trc ht cn
chuyn thuc tính thc thi (x) cho tp tin script bng lnh chmod nh sau:
$ chmod +x first.sh
Sau đó có th triu gi script theo cách th hai tin li hn:
$ first.sh
Có th lnh trên không thc hin thành công và ta s nhn đc thông báo li 'command
not found' (không tìm thy lnh). iu này xy ra bi vì bin môi trng PATH ca bn
thng không cha đng dn hay v trí th mc hin hành.  khc phc, ta có th thêm
vào bin môi trng PATH ch đnh th
 mc hin hành nh sau:
$ PATH=$PATH: .
Nu mun Linux t đng nh th mc hin hành mi khi đng nhp bn có th thêm lnh
PATH=$PATH : . vào cui tp .bash_profile (file đc triu gi lúc h thng đang nhp
- tng t autoexec.bat ca DOS). Tuy nhiên cách gn và đn gin nht mà ta vn
thng làm là đnh rõ du th mc hiên hành ./ ngay trên lnh. Ví d:
$ . / first.sh

Lu ý: i vi tài khon root, không nên thay đi bin môi trng PATH (bng
cách thêm du ch đnh . ) cho phép truy tìm th mc hin hành. iu này không an
toàn và d to ra l hng bo mt. Ví d, mt qun tr h đng nhp di quyn
root, triu gi chng trình ca Linux mà h tng  th mc qui đnh nh /bin,
nu bin PATH cho phép tìm  th mc hin hành thì rt có th nhà qun tr thc
thi chng trình ca ai đó thay vì chng trình Linux  /bin. Vy nên to thói quen
đt du ./ trc mt tp tin đ ám ch truy xut  th mc hin hành.

________________________________________________________________________
Hunh Thúc Cc, Vin CNTT tp hp và biên son
LINUX, Lp trình shell

________________________________________________________________________


9
Mt khi bn tin rng first.sh chy tt, có th di chuyn nó đn th mc khác thích
hp hn th mc hin hành. Nu lnh script ch dành cho mc đích riêng ca bn, bn có
th to ra th mc /bin trong th mc ch (home) mà nhà qun tr qui đnh cho ngi
dùng, sau đó thêm đng dn này vào bin môi trng PATH. Nu mun script đc gi
bi ngi dùng khác, hãy đt nó vào th mc /usr/1ocal/bin. Thông thng, đ cho phép
mt script hay chng trình thc thi, cn đc ngi qun tr cho phép. Nu bn là nhà
qun tr, cng cn cn thn xem xét các script do các ngi dùng khác (hacker chng hn)
đt vào h thng. Ngôn ng script rt mnh, nó có th làm đc hu nh là mi chuyn
k c hy dit h thng!
 ngn script ca b sa đi bi ngi dùng khác, có th s dng các lnh thit
lp quyn (thng phái đng nhp vi t cách root đ làm công vic này):

#cp first.sh /usr/1ocal/bin
#chown root /usr/local/bin/first.sh
#chgrp root /usr/1ocal/bin/first.sh
#chmod u=rwx go=rx /usr/1ocal/bin/firsc.sh

on lnh trên mang ý ngha: chuyn quyn s hu tp tin cho root, root đc toàn
quyn đc sa ni dung và thc thi tp tin, trong khi nhóm và nhng ngi dùng khác
root ch đc phép đc và thc thi. Nên nh mc dù b
n loi b quyn ghi w trên tp tin,
UNTX và Linux vn cho phép bn xoá tp tin này nu th mc cha nó có quyn ghi w.
 an toàn, vi t cách là nhà qun tr, nên kim tra li th mc cha script và bo đm
rng ch có root mi có quyn w trên th mc cha các tp .sh



3. CÚ PHÁP NGÔN NG SHELL

Chúng ta đã thy cách vit lnh và gi thc thi tp tin scirpt. Phn tip theo nay
dành cho bn khám phá sc mnh ca ngôn ng lp trình shell. Trái vi lp trình bng
trình biên dch khó kim li và nâng cp, lp trình script cho phép bn d dàng sa đi
lnh bng ngôn ng vn bn. Nhiu đon script nh có th kt hp li thành mt script
ln mnh m và rt hu ích. Trong th gii UNIX và Linux đôi lúc gi thc thi mt
chng trình, bn khó mà bit đc chng trình đc vit bng script hay thc thi theo
mã ca chng trình nh phân, bi vì tc đ thc thi và s uyn chuyn ca chúng gn
nh ngang nhau. Phn này chúng ta s hc v:
• Bin: kiu chui, kiu s, tham s và bin môi trng
• iu kin: kim tra lun lý Boolean bng shell
• iu khin chng trình: if, elif, for , while, until, case
• Danh shell
• Hàm
• Các hình ni ti ca shell
• Ly v kt qu ca mt lnh
• Tài liu Here

3.1. S dng bin
________________________________________________________________________
Hunh Thúc Cc, Vin CNTT tp hp và biên son
LINUX, Lp trình shell
________________________________________________________________________


10

Thng bn không cn phi khai báo bin trc khi s dng. Thay vào đó bin s
đc t đng to và khai báo khi ln đu tiên tên bin xut hin, chng hn nh trong

phép gán. Mc đnh, tt c các bin đu đc khi to và cha tr kiu chui (string).
Ngay c khi d liu mà bn đa vào bin là mt con s thì nó cng đc xem là đnh
dng chui. Shell và mt vài lnh tin ích s t đng chuyn chui thành s đ thc hin
phép tính khi có yêu cu. Tng t nh bn thân h điu hành và ngôn ng C, cú pháp
ca shell phân bit ch hoa ch thng, bin mang tên foo, Foo, và FOO là ba bin khác
nhau.
Bên trong các script ca shell, bn có th ly v ni dung ca bin bng cách dùng
du $ đt trc tên bin.  hin th ni dung bin, bn có th dùng lnh echo. Khi gán
ni dung cho bin, bn không cn phi s dng ký t $. Ví d trên dòng lnh, bn có th
gán ni dung và hin th bin nh sau:
$ xinahao=hello
$ echo $xinchao
Hello
$ xin chao= "I am here"
$echo $xin chao
I am here
$ xinchao=12+l
$echo $xin chao
12+1

Lu ý, sau du = không đc có khong trng. Nu gán ni dung chui có khong
trng cho bin, cn bao bc chui bng du “ “.

Có th s
 dng lnh read đ đc nhp liu do ngi dùng đa vào và gi li trong bin
đ s dng. Ví d:
$ read yourname
XYZ
$echo "Hello " $yourname
Hello XYZ

Lnh read kt thúc khi bn nhn phím Enter (tng t scanf ca C hay readln ca
Pascal).



3.1.1. Các kí t đc bit (Metalcharacters ca Shell)

3.1.1.1 Chuyn hng vào/ra

Mt tin trình Unix/Linux bao gi cng gn lin vi các đu x lí các dòng (stream) d
liu: đu vào chun (stdin hay 0), thng là t
 bàn phím qua chc nng getty(); đu ra
chun (stdout, hay 1), thng là màn hình, và c s d liu li h thng (stderr, hay 2).
Tuy nhiên các hng vào/ra có th thay đi đc bi các thông báo đc bit:
Kí hiu Ý ngha ( … tng trng cho đích đi hbg)
________________________________________________________________________
Hunh Thúc Cc, Vin CNTT tp hp và biên son
LINUX, Lp trình shell
________________________________________________________________________


11
> u ra hng ti …
>> Ni vào ni dung ca …
< Ly đu vào t < …
<< word đu vào là  đây …
2> đu ra báo li s hng vào …
2>> đu ra báo li hng và ghi thêm vào …

Ví d:

$date > login.time
Lnh date không kt xut ra đu ra chun (stdout) mà ghi vào tp login.time. >login.time
không phi là thành phn ca lnh date, mà đn gin mô t tin trình t
o và gi kt xut 
đâu (bình thng là màn hình). Nhìn theo cách x lí thì nh sau: c cm lnh trên cha
hai phn: lnh date, tc chng trình thc thi, và thông đip (>login.time) thông báo cho
shell bit kt xut lnh s đc x lí nh th nào (khác vi mc đnh. Bn thân date cng
không bit chuyn kt xut đi đâu, shell chn mc đnh).

Ví d:
$cat < file1
Bình thng cat nhn và hin th ni dung tp có tên (là đi đu vào). Vi lnh trên cat
nhn ni dung t file1 và kt xut ra màn hình. Thc cht không khác gì khi gõ:
$cat file1.
Hãy xem:
$cat < file1 > file2
Lnh này thc hin nh th nào ? Theo trình t s nh sau: cat nhn ni dung ca file1
sau đó ghi vào tp có tên file2, không đa ra stdout nh mc đnh. Lnh cho thy ta có
th thay đi đu và đu ra cho lnh nh th nào. Nhng lnh cho phép đi đu ra/vào gi
chung là qúa trình lc (filter).

Ví d:
$cat file1 < file2
Lnh này ch hin th ni dung ca file1, không gì hn. Ti sao ? cat nhn đi đu vào là
tên tp. Nu không có đi nó nhn t stdin (bàn phím). Có đi thì chính là file1 và đu ra
là stdout. Trng hp này gi là b qua đi hng. Cái gì  đây là quan trng ? u
ra/vào ca lnh đã đi hng cng không có ngha là s bo đm rng s đi hng s
đc s dng Mt ln na cho thy lnh bn thân nó không hiu rng đã có s đi hng
và có lnh chp nhn đi hng vào/ra, nhng không phi tt c. Ví d
$date < login.time

date khác cat, nó không kim tra đu vào, nó bit phi tìm đu vào  đâu. i hng 
đây không có tác dng.

Ví d
$cat < badfile 2> errfile
Thông thng các li h thng qun lí đu  stderr và s in ra màn hình. Tuy nhiên có th
chuyn hng báo li, ví d vào m
t tp (chng hn logfile) mà không đa ra mahn hình.
Ví d trên là nh vy. Ta bit stderr là tp có mô t tp = 2, do vy 2>errfile có ngha đi
đu ra ca stderr vào mt tp, tc ghi báo li vào tp xác đnh.
________________________________________________________________________
Hunh Thúc Cc, Vin CNTT tp hp và biên son
LINUX, Lp trình shell
________________________________________________________________________


12

Nhng gì va đ cp tác đng trên tp vào/ra. Ta cng có cách x lí ngay trong
mt dòng ca tp, cái đó gi là đi hng trong dòng (in-line Redirection). Lai này bao
gm hai phn: đi hng (<<) và du hiu đánh du (là bt kì kí t gì) ca dòng d liu
vào.

Ví d:
$cat << EOF # du hiu đánh du ch
n  đây là EOF
> Xin chao
> ….
> EOF (và gõ ENTER)
Ngay lp tc trên màn hình s là:

Xin chao

 đây EOF là du hiu đánh du, hay còn gi là th bài (token). iu đáng lu ý là: 1.
cùng mt dòng d liu, phai đc kt thúc; 2. token phi đng ngay  đu dòng. Ví d
trên có mt chú ý: du > gi là du nhc th cp, nó cho bit dòng lnh đa vào dài hn
là 1 dòng và cng là du hiu shell thông báo nó hòai vng nhn nhiu (thông tin)  đu
vào.
Hãy th vi ví d sau:
$ cat << EOF
> Logged in
> EOF > login.time
$ date >> login.time
$cat login.time
Login in
Fri May 19 12:40:15 PDT 2004

3.1.1.2 Các kí t đc bit kim soát tin trình

1. & (Ampersand) : đt mt tin trình (chng trình) vào ch đ chy nn
(background process). Bn thân Unix không có khái nim gì v tin trình chy nn hay
tin trình tng tác (foreground), mà shell điu khin vic chy các tin trình. Vi &
chng trình s t chy và shell quay ngay v tng tác vi ngi dùng, tr li du nhc
ngay. Ti
n trình nn có nhiu cách đ kim soát.
Ví d:
$sort huge.file > sorted.file &
$
Bng lnh ps s thy lnh sort đang chy kèm vi só ID ca tin tình đó.
Bng lnh
$ jobs

[1]
s thy s hiu ca lnh đang chy ngm.
 kt thúc thc thi, dùng
$ kill 1234 #1234 là só ID ca tin trình sort
 quay li ch đ tng tác:
________________________________________________________________________
Hunh Thúc Cc, Vin CNTT tp hp và biên son
LINUX, Lp trình shell
________________________________________________________________________


13
$ fg 1

2. Ngoc đn ( ; ) Dùng đ nhóm mt s lnh li, phân cách bi ;
Ví d:
$ (date ; who) > system.status
$ cat system.status
(Hãy xem kt xut trên màn hình)

3. Du nháy ` ` (backquotes) (là du  phím đi cùng vi ~)

Hay còn gi là du thay th. Bt kì lnh nào xut hin bên trong du nháy s đc thc
hin trc và kt qu ca lnh
đó s thay th đu ra chun (stdout) trc khi lnh trong
dòng lnh thc hin.
Ví d:
$ echo Logged in `date` > login.time
s nói cho shell đi thc hin date trc tiên, trc khi thc hin các phn khác còn li
ca dòng lnh, tc sau đó mi thc hin lnh echo. Vy cách din đt dòng lnh trên nh

sau:
echo Logged in Fri May 12:52:25 UTC 2004 > login.time
Tc là: 1. thc hin date vi kt qu Fri May 12:52:25 UTC 2004 không hin ra stdout
(màn hình), nhng s là đu vào ca echo;
2. sau đó lnh echo s echo Logged in Fri May 12:52:25 UTC 2004, nhng không
đa ra màn hình (stdout) mà đi hng vào tp login.time.
Nu gõ $ cat login.time, ta có kt xut t tp này ra màn hình:
Logged in Fri May 12:52:25 UTC 2004

1.Hãy th vi lnh:
$echo Logged in Fri May 12:52:25 UTC 2004
Kt qu ?
2. Kt hp:
$cat << EOF
> Logged in `date`
> EOF > Login.time (ENTER)
Sau đó thc hin:
$ cat login.time
Kt qu ?

4. ng dn (Pipelines)
Shêll cho phép kt qu thc thi mt lnh (đu ra ca lnh), kt hp tr
c tip (ni vào) đu
vào ca mt lnh khác, mà không cn x lí trung gian (lu li trc ti tp trung gian).
Ví d:
$who | ls –l
u ra (stdout) ca who (đáng l s ra màn hình), slà đi vào (stdin) ca ls –l.
Ví d:
$ (date ; who) | ls -


________________________________________________________________________
Hunh Thúc Cc, Vin CNTT tp hp và biên son
LINUX, Lp trình shell
________________________________________________________________________


14
Tóm tt:
cmd & đt lnh cmd chy nn (background)
cmd1 ; cmd2 chy cmd1 trc, sau đó chy cmd2
(cmd) thc hin cmd trong mt shell con (subshell)
`cmd` đu ra ca cmd s thay cho đàu ra ca lnh trong dòng lnh
cmd1 | cmd2 ni đu ra ca cmd1 vào đu vào ca cmd2

3.1.1.2 Du bc chui (quoting)

Shell có mt tp các kí t đc bit mà hiu lc ca chúng là đ vô hiu hóa ý ngha ca
các kí t đc bit khác. Khi mt kí t đc bit b gii tr hiu lc, ta gi kí t đó là b
quoted.
Trc khi tip tc chúng ta cn hiu mt s tính cht ca du bc chui mà shell
quy đnh. Thông thng, tham s dòng lnh thng cách nhau bng khong trng.
Khong trng có th là ký t spacebar, tab hoc ký t xung dòng. Trng hp mun
tham s ca mình cha đc c khong trng, cn phi bc chui bng du nháy đn '
hoc nháy kép " .
Du nháy kép đc dùng trong trng hp bin chui ca bn có khong trng. Tuy
nhiên vi du nháy kép, ký hiu bin $ vn có hiu lc. Ni dung ca bin s đc thay
th trong chui. Du nháy đn s có hiu lc mnh hn. Nu tên bin có ký t $ đt trong
chui có du nháy đn, nó s b vô hiu hóa. Có th dùng du \ đ hin th ký t đt bit
$ trong chui.


1. Backslash (\)
Ví d:
$cat file1&2 lnh này gây ra nhiu li, bi có s hiu nhm & trong khi nó đn
gin là thành phn ca tên tp (file1&2).  đc nh ý:
$cat file1\&2 s cho kt quae nh momg mun: đa ni dung ca tp có tên
file1&2 ra màn hình. Du \ đã gii tr ý ngha đc bit ca &.


Các ví d khác v “ ” hay ‘ ‘:

Ví d 3-1: variables.sh
#!/bin/sh

myvar="Hi there"

echo $myvar
echo "message : $myvar"
echo 'message : $myvar'
echo "messgae :\$myvar"

echo Enter some text
read myvar

echo '$myvar' now equals $myvar

________________________________________________________________________
Hunh Thúc Cc, Vin CNTT tp hp và biên son
LINUX, Lp trình shell
________________________________________________________________________



15
exit 0

Kt xut khi thc thi script:
Hi there
message : Hi there
message : $myvar
message : $myvar
Enter some text
Hello World
$myvar now equals Hello World

Cách chng trình làm vic:
Bin myvar đc to ra và khi gán giá tr chui Hi there. Ni dung ca bin sau
đó đc hin th bng lnh echo trong các trng hp bc chuôi bng nháy kép, nháy đn
và du hin th ký t đc bit \. Tóm li 'nu mun thay th ni dung bin trong mt
chui, cn bc chui bng nháy kép. Nu mun hin th toàn b
 ni dung chui, hãy dùng
nháy đn.

3.1.2. Biên môi trng (environment variable)

Khi trình shell khi đng nó cung cp sn mt s bin đc khai báo và gán tr
mc đnh. Chúng đc gi là các bin môi trng. Các bin này thng đc vit hoa đ
phân bit vi bin do ngi dùng t đnh ngha (thng là ký t không hoa). Ni dung
các bin này thng tùy vào thit lp ca h thng và ngi qun tr cho phép ngi
dùng h thng s dng. Danh shell ca các bin môi trng là khá nhiu, nhng nhìn
chung nên nh mt s bin môi trng ch yu sau:


Bin môi trng Ý ngha
$HOME Cha ni dung ca th mc ch. (Th mc đu tiên khi ngi
dùng đng nhp)
$PATH Cha danh shell các đng dn (phn cách bng dn hai chm :).
Linux thng tìm các trình cn thi hành trong bin $PATH.
$PS1 Du nhc (prompt) hin th trên dòng lnh. Thông thng là $
cho user không phi root.
$SP2 Du nhc th cp, thông báo ngi dùng nhp thêm thông tin trc
khi lnh thc hin.Thng là du >.
$IFS Du phân cách các trng trong danh shell chui. Bin này cha
danh shell các ký t mà shell dùng tách chui (thng là tham s
trên dòng lnh). Ví d $IFS thng cha ký t Tab, ký t trng
hoc ký t xung hàng.
$0 Cha tên chng trình gi trên dòng lnh.
$# S tham s truyn trên dòng lnh
$$ Mã tin trình (process id) ca shell script thc thi. Bi s
 process
id ca tin trình là duy nht trên toàn h thng vào lúc script thc
thi nên thng các lnh trong script' dùng con s này đ to các tên
file tm. Ví d /tmp/tmpfile_$$.
________________________________________________________________________
Hunh Thúc Cc, Vin CNTT tp hp và biên son
LINUX, Lp trình shell
________________________________________________________________________


16
Mi môi trng mà uer đng nhp cha mt s danh shell bin môi trng dùng cho mc
đích riêng. Có th xem đanh shell này bng lnh env.  to mt bin môi trng mi,
có th dùng lnh export ca shell (mt s shell s dng lnh setenv).


3.1.3. Bin tham s (parameter variable)

Nu cn tip nhn tham s trên dòng lnh đ x lý, có th dùng thêm các bin môi
trng sau:

Bin tham s Ý ngha
$1, $2, $3 . . . V trí và ni dung ca các tham s trên dòng lnh theo th t t
trái sang phi.
S* Danh shell ca tt c các tham s trên dòng lnh. Chúng đc lu
trong mt chui duy nht phn cách bng ký t đu tiên quy đnh
trong bin $IFS
$@ Danh shell các tham s đc chuyn thành chui. Không s dng
du phân cách ca bin IFS.

 hiu rõ s khác bit ca bin $ * và $@, hãy xem ví d sau:
$IFS= "A”
$set foo bar bam
$echo “$@”
foo bar bam
$echo "$*”
foo^ bar^bam
$unset IFS
$echo "$*"
foo bar bam
Ta nhn thy, lnh set tip nhnn 3 tham s trên dòng lnh là foo bar bam. Chúng nh
hng đn bin môi trng $* và $@. Khi IFS đc qui đinh là ký t ^ , $* cha danh
shell các tham s phân cách bng ký t ^ . Khi đt IFS v NULL bng lnh unset, bin $*
tr v danh shell thun tuý ca các tham s tng t bin $@.
Bin $# s cha s tham s ca lnh, trong tr

ng hp trên ta có:
$echo " $ # "
3
Khi lnh không có tham s thì $0 chính là tên lnh còn $# tr v giá tr 0.

on trình mu sau s minh ha mt s cách đn giãn x lý và truy xut bin môi
trng.

Ví d3-2: try_variables.sh

#!/bin/sh

salutation="Hello"
echo $salutation
echo "The program $0 is now running"
________________________________________________________________________
Hunh Thúc Cc, Vin CNTT tp hp và biên son
LINUX, Lp trình shell
________________________________________________________________________


17
echo "The second parameter was $2"
echo "The first parameter was $1"
echo "The parameter list was $*"
echo "The user's home directory is $HOME"

echo "Please enter a new greeting"
read salutation


echo $salutation
echo "The script is now complete"

exit 0

Lu tên tp là try-variables.sh, đi thuc tính thc thi x cho tp tin bng lnh:
$chmod +x try_variablebles.sh
Khi chy try-variables.sh t dòng lnh, bn s nhn đc kt qa kt xut nh
sau:
$./try_variables.sh foo bar baz
Hello
The program . /try_vanables.sh is now running
The second parameter was bar
The first parameter was foo
The parameter list was foo bar baz
The user's home directory is /home/xyz #tên ngi dùng login là xyz
please enter a new greeting
Xin chao!
Xin chao!
The scnpt is now complete


3.2. iu kin

Nn tng c bn trong tt c ngôn ng lp trình, đó là kh nng kim tra điu kin
và đa ra quyt đnh r nhánh thích h
p tùy theo điu kin đúng hay sai. Trc khi tìm
hiu cu trúc điu khin ca ngôn ng script, ta hãy xem qua cách kim tra đi kin.
Mt script ca shell có th kim tra mã li tr v ca bt k lnh nào có khá nng
triu gi t dòng lnh, bao gm  nhng tp tin lnh script khác. Ó là lý do ti sao

chúng ta thng s dng lnh exit  cui mi scipt khi kt thúc.

3.2.1. Lnh test hoc [ ]

Thc t, các script s dng lnh [] hoc test đ kim tra điu kin boolean rt
thng xuyên. Trong hu ht các h thng UNIX và Linux thì [ ] và test có ý ngha tng
t nhau, thng lnh [ ] đc dùng nhiu hn. Lnh [ ] trông đn gin, d hiu và rt gn
vi các ng lp trình khác.

Trong mt s shell ca Unix, lnh test có kh nng là mt li triu gi đn
chng trình bên ngoài ch không phi lnh ni ti ca ngôn ng script. Bi vì
________________________________________________________________________
Hunh Thúc Cc, Vin CNTT tp hp và biên son
LINUX, Lp trình shell
________________________________________________________________________


18
test ít khi đc dùng và hu ht các lp trình viên có thói quen thng to các
chng trình vi tên test, cho nên khi th lnh test không thành công bên trong
script, thì hãy xem li đây đó bên trong h thng có mt chng trình tên là test
khác bit nào đó đang tn ti. Hãy th dùng lnh which test, lnh này s tr v
cho bn đng dn đn th mc test đc triu g
i. Chng hn /bin/test hay
/usr/bin/test.

Dc đây là cách s dng lnh test đn gin nht. Dùng lnh test đ kim tra xem
file mang tên hello.c có tn ti trong h thng hay không. Lnh test trong trng hp này
có cú pháp nh sau: test -f <mename>, trong script ta có th vit lnh theo cách sau:


if test -f hello.c
then
. . .
fi

Cng có th s dng [ ] đ thay th test
if [-f hello.c ]
then
. . .
fi

Mà li và giá tr tr v ca lnh mà test kim tra s quyt đnh điu kin kim tra

đúng hay sai.
Lu ý, phi đt khong trng gia lnh [ ] và biu thc kim tra.  d nh th
xem [ ] tng đng vi lnh test, và d nhiên gia mt lnh và tham s truyn
cho lnh phi phân cách nhau bng khong trng đ trình biên dch có th hiu.

Nu thích đt t khóa then chung mt dòng vi lnh if, bn phi phân cách then
bng du chm phy (;) nh sau:
if [ -f hello.c ] ; then
. . .
fi
iu kin mà lnh test cho phép kim tra có th ri vào mt trong 3 kiu sau:

So sánh chui
So sánh Kt qu
stringl = string2 true nu 2 chui bàng nhau (chính xác tng ký t)
tring1 != string2 true nu 2 chui không bng nhau
-n string1 true nu string1 không rng

-z stringl true nu string1 rng (chui null)

So sánh toán hc
So sánh Kt qu
expression1 -eq expression2 true nu hai biu thc bng nhau
expression1 -ne expression2 true nu hai biu thc không b
ng nhau
________________________________________________________________________
Hunh Thúc Cc, Vin CNTT tp hp và biên son
LINUX, Lp trình shell
________________________________________________________________________


19
expression1 -gt expression2 true nu biu thc expression1 ln hn expression2
expreesion1 -ge expression2 true nu biu thc expression1 ln hn hay bng
expression2
expression1 -lt expression2 true nu biu thc expression1 nh hn expression2
expression1 -le exprebbion2 true nu biu thc expression1 nh hn hay bng
expression2
!expression true nu biu thc expression là false (toán t not)

Kim tra đi
u kin trên tp tin
-d file true nu file là th mc
-e file true nu file tn ti trên đa
-f file true nu file là tp tin thông thng
-g file true nu set-group-id đc thit lp trên file
-r file true nu file cho phép đc
-s f ile true nu kích thc file khác 0

-u file true nu set-ser-id đc áp đt trên file
-w file true nu file cho phép ghi
-x file true nu file đc phép thc thi

Lu ý v mt lch s thì tùy chn -e không kh chuyn (portable) và -f th
ng đc s
dng thay th.

Câu hi có th đt ra là set-group-id và set-ser-id (còn đc gi là set-gid và set-
uid) mang ý ngha gì. Set-uid cho phép chng trình quyn ca ch th s hu
(owner) thay vì quyn ca user thông thng. Tng t set-gid cho phép chng
trình quyn ca nhóm.

Tt cá các điu kin kim tra tp tin đu yêu cu file phi tn ti trc đó (có
ngha là lnh test -f filename phi đc gi trc). Lnh test hay [ ] còn có thêm nhiu
điu kin kim tra khác na, nhng hin thi ta cha dùng đn. Có th tham kho chi tit
test bng lnh help test t du nhc ca h thng.

3.3. Cu trúc điu khin

Shell cung cp cu trúc lnh điu khin rt ging vi các ngôn ng lp trình khác
đó là if, elif, for, while, until, case. i vi mt vài cu trúc lnh (ví d nh case), shell
đa ra cách x lý uyn chuyn và mnh m hn. Nhng cu trúc điu khin khác nu có
thay đi ch là nhng thay đi nh không đáng k.
Trong các phn sau statements đc hiu là biu thc lnh (có th bao gm mt
tp hp các lnh) s đc thc thi khi điu kin kim tra condition đc tho
mãn.

1 3.3.1. Lnh if


Lnh if tuy đn gin nhng đc s dng nhiu nht. if kim tra điu kin đúng
hoc sai đ thc thi biu thc thích hp
________________________________________________________________________
Hunh Thúc Cc, Vin CNTT tp hp và biên son
LINUX, Lp trình shell
________________________________________________________________________


20
if condition
then
statements
else
statements
Ví d, đon script sau s đng if tùy vào cu trá li ca bn mà đa ra li chào thích hp

Ví du 3-3 if_control.sh

#!/bin/sh

echo "Is it morning? Please answer yes or no"
read timeofday

if [ $timeofday = "yes" ]; then
echo "Good morning"
else
echo "Good afternoon"
fi

exit 0



Kt qu kt xut ca script
$./ if_control.sh
Is it mornining ? Please answer yes or no
yes
Good morning
$

 ví d trên chúng ta đã s dng cú pháp [ ] đ kim tra điu kin thay cho lnh test.
Biu thc kim tra xem ni dung ca bin $timeofday có khp vi chui "yes" hay
không. Nu có thì lnh echo cho in ra chui “Good morningg”, nu không (mnh đ else)
in ra chui “Goođ afternoon".

Shell không đòi hi phi canh l hay tht đu dòng cho tng lnh. Chúng ta canh
l đ có pháp đc rõ ràng. Mc dù vy sau này bn s thy ngôn ng ca
chng trình make s yêu cu canh l và xem đó là yêu cu đ nhn dng lnh.

3.3 2. Lnh elif

Tht không may, có rt nhiu vn đ phát sinh vi đon trình script trên. Tt c tr
li khác vi “yes” đu có ngha là “no”. Chúng ta có th khc phc điu này bng cách
dùng cu trúc điu khin elif. Mnh đ này cho phép kim tra điu kin ln th hai bên
trong else. Script di đãy ca có th đc sa đi hoàn chnh hn, bao gm c in ra
thông báo li nu ngi dùng không nhp đúng câu tr li “yes” hoc “no”.

Ví du 3-4: elif_control.sh

________________________________________________________________________
Hunh Thúc Cc, Vin CNTT tp hp và biên son

LINUX, Lp trình shell
________________________________________________________________________


21
#!/bin/sh

echo "Is it morning? Please answer yes or no"
read timeofday

if [ $timeofday = "yes" ]; then
echo "Good morning"
elif [ $timeofday = "no" ]; then
echo "Good afternoon"
else
echo "Sorry, $timeofday not recognized. Enter yes or no"
exit 1
fi

exit 0

Cng đn gián nh ví d 3-3, nhng chúng ta s dng thêm elif đ kim tra trng hp
ngi dùng không nhp “no". Thông báo li đc in ra và mã li tr v bng lnh exit là
1. Trng hp hoc “yes” hoc “no” đc nhp vào, mã li tr v s là 0.




3.3.3. Vn đ phát sinh vi các bin


elif trong ví d trên khc phc đc hu ht các điu kin nhp li
u và yêu cu
ngi dùng nhp đúng trc khi ra quyt đnh thc thi tip theo. Mc dù vy, có mt vn
đ khá tinh t còn li, nu chy li elif_control.sh nói trên, nhng thay vì nhp vào mt
chui nào đó, hãy gõ Enter (to chui rng cho bin $timeofday), s nhn đc thông báo
li ca shell nh sau:

[ : = : unary operator expected

iu gì xy ra ? Li phát sinh ngay mnh đ if đu tiên. Khi bin timeofday đc kim
tra nó cho tr là rng và do đó lnh if s đc shell din dch thành:

if [= “yes " ]

và d nhiên shell không hiu phi so sánh chui “yes" vi cái gì.  tránh li này cn bc
ni dung bin bng du bao chui nh sau:

if [ “$timeofdayl” ="yes”]

Trong trng hp này nu chui nhp vào là rng, shell s din dch biu thc thành:
if [ “ “ =”yes”]

và script s chy tt. Elif_control.sh có th sa li hoàn chnh hn nh sau:

________________________________________________________________________
Hunh Thúc Cc, Vin CNTT tp hp và biên son
LINUX, Lp trình shell
________________________________________________________________________



22
Ví du: 3-5: elif_control2.sh

#!/bin/sh

echo -n "Is it morning? Please answer yes or no: "
read timeofday

if [ "$timeofday" = "yes" ]; then
echo "Good morning"
elif [ "$timeofday" = "no" ]; then
echo "Good afternoon"
else
echo "Sorry, $timeofday not recognized. Enter yes or no"
exit 1
fi

exit 0

Hãy kim tra li elif_controi2.sh bng cách chi nhn Enter khi shell đa ra câu
hi. Script gi đây chy rt bo đm và chun.

Lnh echo thng xung hàng sau khi đa ra thông báo. Có th đùng lnh printf
(s đ cp  phn sau) thay cho echo. Mt vài shell cho phép lnh echo -e trên
mt dòng, nhng chúng không phi là ph bin đ bn s dng.

3.3.4. Lnh for

S dng for đ lp li mt s ln vi các giá tr xác đnh. Phm vi lp có th nm
trong mt tp hp chui ch đnh tng minh bi chng trình hay là kt qa tr v t

mt bin hoc biu thc khác.
Cú pháp:
for variable in values
do
statemens
done

Ví d sau s in ra các giá tr chui trong tp hp:

Ví du 3-6: for_loop.sh

#!/bin/sh

for foo in bar fud 13
do
echo $foo
done

exit 0


Kt qu kt xut s là
________________________________________________________________________
Hunh Thúc Cc, Vin CNTT tp hp và biên son
LINUX, Lp trình shell
________________________________________________________________________


23


$./ for_loop.sh
bar
fud
13

foo là mt bin dùng trong vòng lp for đ duyt tp hp gm 3 phn t (cách nhau bng
khong trng). Mc đnh shell xem tt c các giá tr gán cho bin là kiu chui cho nên 13
 đây đc xem là chui tng t nh chui bar và fud.

iu gì s xy ra nu bn thay th lnh for foo in barr fud 13 thành for foo in
“bar fud 13”. Hãy nh li, du nháy kép cho phép coi tt c ni dung bên trong
nháy kép là mt bin chui duy nht. Kt qu kt xut nu s dng du nháy kép,
lnh echo ch đc gi mt ln đ in ra chui "bar fud 13 ".

for thng dùng đ duyt qua danh shell tên các tp tin. Bng cách dùng ký t đi din *
(wildcard)  ví d first.sh, ta đã thy cách for tìm kim tp tin kt hp vi lnh grep. Ví
d sau đây cho thy vic m rng bin thành tp hp s dng trong lnh for. Gi s bn
mun in ra tt c các tp *.sh có ký t đu tiên là f



Ví du 3-7: for_loop2.sh

#!/bin/sh

for file in $(ls f*.sh); do
lpr $file
done

Ví d trên đây cng cho thy cách s dng cú pháp $(command) (s đc chúng

ta tìm hiu chi tit hn trong phn sau). Danh shell ca các phn t trong lnh for đc
cung cp bi kt qu tr v ca lnh ls f* và đc bc trong cp lnh m rng bin $ ( ) .
Bin m rng nm trong du bao $ (command) ch đc xác đinh khi lnh
command thc thi xong.

3.3.5. Lnh while

Mc dù lnh for cho phép lp trong mt tp hp giá tr bit trc, nhng trong
trng hp mt tp hp ln hoc s ln lp không bit trc, thì for không thích hp. Ví
d .
for foo in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
do
echo $foo
done

Lnh while cho phép thc hin lp vô hn khi điu kin kim tra vn còn đúng.
________________________________________________________________________
Hunh Thúc Cc, Vin CNTT tp hp và biên son
LINUX, Lp trình shell
________________________________________________________________________


24
Cú pháp ca while nh sau:
while condition do
statements
done
Ví d sau s cho thy cách while liên tc kim tra mt khu (password) ca ngi dùng
cho đn khi đúng bng chui secret, mi chp nhn.


Ví du: 3-8: password.sh

#!/bin/sh

echo "Enter password"
read trythis

while [ "$trythis" != "secret" ]; do
echo "Sorry, try again"
read trythis
done

exit 0

Kt xut ca scnpt
$./password.sh
Enter password:
abc
Sorry, try again
secret #gõ đúng
$
Mc dù đ password hin th khi nhp liu rõ ràng là không thích hp, nhng 
đây ta ch yu minh ha lnh while. Lnh while liên tc kim tra ni dung bin $trythis,
yêu cu nhp li d liu bng lnh read mt khi $trythis vn cha bng vi chui "secret
".
Bng cách s dng bin đm và biu thc so sánh toán hc, while
hoàn tòan có th thay
th for trong trng hp tp d liu ln. H theo dõi ví d sau:

Ví d: 3-9 while_for.sh


#!/bin/sh

foo=1

while [ "$foo" -le 16 ]
do
echo "Here $foo"
foo=$(($foo+1))
done

exit 0

Lu ý, cú pháp $( ( ) ) do shell ksh đã xng. Cú pháp này dùng đ đánh giá và
________________________________________________________________________
Hunh Thúc Cc, Vin CNTT tp hp và biên son
LINUX, Lp trình shell
________________________________________________________________________


25
c lng mt biu thc. Vi các shell c khác có th thay th cú pháp này bng
lnh expr. Tuy nhiên expr không hiu qu. Bt c khi nào, nu có th hãy nên
dùng $ ( ( ) ) thay cho expr.

script while_for.sh s dng lnh [ ] đ kim tra giá tr ca bin $foo vn còn nh hn hay
bng 16 hay không. Nu còn, lnh lp while s in ra tng cng dn ca bin $foo.

3.3.6. Lnh intil


Cú pháp ca lnh until nh sau:
until condition
do
statements
done

Lnh until tng t lnh while nhng điu kin kim tra bi đo ngc li. Vòng lp s b
dng nu điu kin kim tra là đúng. Ví d sau s s dng lnh until đ ch mt user nào
đó đng nhp:1

Ví d 3-10: until_user.sh

#!/bin/sh
echo "Locate for user "
until who | grep "$1" > /dev/null
do
sleep 60
done

echo -e \\a


echo "***** $1 has just logged in *****"

exit 0

 th lnh này, nu chy ngoài màn hình console, hãy dùng hai màn hình o (Alt+F1 và
Alt+F2), mt màn hình dùng chy script until_user.sh, màn hình kia dùng đng nhp vi
tên user mun kim tra. Nu trong ch đ đ ha, bn có th m hai ca s terminal và s
d hình dung hn. Hãy chy until_user.sh t mt màn hình nh sau:

$./until_user.sh xyz
Locate for user . . .
Script s ri vào vòng lp ch user tên là xyz dng nhp. Hãy nhp t mt màn hình khác
(vi user tên là xyz), ta s thy màn hình đu tiên đa ra thông báo cho thy vòng lp
until ch
m dt

* * * * * xyz has just logged in * * * * *

Cách chng trình làm vic:
________________________________________________________________________
Hunh Thúc Cc, Vin CNTT tp hp và biên son

×