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

Tài liệu lập trình shell Linux - Unix

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 (1.16 MB, 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

×