chuong 3 - lap trinh shell
TRANSCRIPT
1
2
Linux và Shell
Sử dụng Shell như ngôn ngữ lập trình
Sử dụng biến
Cấu trúc điều khiển
Danh sách thực thi
Hàm
Dữ liệu kiểu mảng, chuỗi
Các lệnh nội tại của Shell
Lấy kết quả của một lệnh
Debug
Lập trình C shell
• Shell:
– Là trình diễn dịch trung gian, cung cấp khả năng giao tiếp với hạt nhân, gọi là hệ vỏ (shell)
• Linux cung cấp các Shell tương tác rất mạnh mẽ.
• Shell có thể diễn dịch và cho phép người dùng script dưới dạng ngôn ngữ C.
• Shell dịch các lệnh ta 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
3
Tương tác giữa Shell, chương trình ứng dụng, hệ X-Window và
hạt nhân Linux:
4
Các trình ứng dụng
csh (C Shell)
Bash (Bourne Again
Shell)
X-Window (Shell đồ họa)
Hạt nhân
Linux
Có 2 cách để viết chương trình điều khiển shell:
- Nhập từ dòng lệnh
- Gộp các lệnh vào một file, thực thi như 1 file chương trình
1. Điều khiển shell từ dòng lệnh:
Ví dụ: Tìm và hiện thị nội dung của các file chứa chuỗi Hello.
C1: dùng lệnh grep để tìm ra từng file, sau đó dùng lệnh more
C2: ta có thể dùng lệnh điều khiển shell tự động như sau:
$ for file in *
> do
> if grep -l „Hello‟ $file
> then
> more $file
> fi
> done
5
2. Điều khiển shell bằng tập tin kịch bản (script file)
Dùng lệnh cat hay một trình soạn thảo khác để soạn thảo nội dung tệp tin
Cat > vidu1.sh
#! /bin/sh
for file in *
do
if grep -l „Hello‟ $file
then
more $file
fi
done
exit 0
Chú ý:
#: chú thích
#!: yêu cầu shell hiện tại triệu gọi shell (sh) hoặc bất kỳ một chương trình nào mà ta muốn chạy trước khi script tiếp theo được diễn dịch
exit: đảm bảo rằng script sau khi thực thi sẽ trả về mã lỗi thành công
+ Tên file: đuôi .sh hoặc có thể bất kỳ tên mở rộng nào
+ Để nhận biết một file là script hay không ta dùng lệnh: file vidu 6
3. Thực thi script
- Cần chuyển thuộc tính thực thi (x) cho tập tin:
chmod +x <filename>
- Thực thi như sau: ./<filename>
- Lưu ý: chỉ rõ đường dẫn
- Để ngăn script không bị sửa đổi bởi người sử dụng khác, ta có thể sử dụng các lệnh thiết lập quyền:
- Ví dụ:
cp vidu1.sh /usr/local/bin
chown root /usr/local/bin/vidu1.sh
chgrp root /usr/local/bin/vidu1.sh
chmod u=rwx, go=rx /usr/local/bin/vidu1.sh
-Ý nghĩa:
- root được toàn quyền đọc, sửa, thực thi tập tin
- nhóm và người sử dụng được phép đọc và thực thi. - Chú ý: mặc dù tệp tin không được phép ghi (w) nhưng có thể xóa bỏ tập tin này nếu thư mục chứa tập tin có quyền ghi.
7
Đặc điểm biến:
Biến sẽ được tự động tạo ra và khai báo khi lần đầu tiên xuất hiện.
Mặc định, các biến đều được khởi tạo và chứa trị kiểu chuỗi.
Shell và một vài lệnh sẽ thực hiện đổi chuỗi ra số khi có yêu cầu.
Biến có phân biệt chữ hoa chữ thường.
Tên biến: là một chuỗi ký tự bắt đầu bằng chữ cái hoặc dấu “_”.
ví dụ: myvar, _x
8
1. Sử dụng biến do NSD tạo ra
Gán giá trị cho biến: <tên biến>=<giá trị>
Ví dụ:
x=1000
• Sử dụng giá trị của biến: $<tên biến>
• Hiện thị nội dung biến, dùng lệnh echo:
Ví dụ: echo $x
echo -n $x # -n: Không xuống dòng
• Đọc giá trị biến từ bàn phím: read <biến>
Ví dụ: $read name
$echo Hello $name
9
Lệnh echo
Dùng để hiển thị dòng văn bản, giá trị biến …
Cú pháp : echo [options] [chuỗi, biến…]
Các option :
-n : không in ký tự xuống dòng.
-e : cho phép hiểu những ký tự theo sau dấu \ trong chuỗi
\a : alert (tiếng chuông)
\b : backspace
\c : không xuống dòng
\n : xuống dòng
\r : về đầu dòng
\t : tab
\\ : dấu \
ví dụ : echo –e “một hai ba \a\t\t bốn \n” 10
Dấu bọc chuỗi (quote)
† Chuỗi chứa khoảng trắng nên cần bọc bởi dấu nháy đơn ' hay nháy kép "
† Dấu nháy kép: nếu chuỗi có kí hiệu $ thì nó vẫn có hiệu lực
† Dấu nháy đơn: mạnh hơn, vô hiệu hóa kí tự $ trong chuỗi.
† Dùng dấu \ để hiển thị kí tự đặc biệt $
† Ví dụ: vidu2.sh
#! /bin/sh
myvar="Hi there"
echo $myvar -> Hi there
echo "$myvar“ -> Hi there
echo '$myvar„ -> $myvar
echo "\$myvar“ -> $myvar
echo '\$myvar„ -> \$myvar
Dấu `: Nháy ngược, thực thi lệnh
echo “hôm nay là `date`“ 11
2. Biến môi trường (environment variable)
- Được khai báo và gán trị mặc định Shell khởi động.
- Được viết hoa để phân biệt với các biến do người dùng định nghĩa,
có nội dung tùy vào thiết lập của hệ thống và người quản trị.
- Một số biến môi trường:
$HOME: chứa nội dung thư mục chủ.
$PATH: chứa danh sách đường dẫn. Linux thường tìm các lệnh cần
thi hành trong biến $PATH
$PS1: dấu nhắc, thường là $ cho user không phải root
$PS2: 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 thực hiện lệnh (>)
$IFS: dấu phân cách các trường trong danh sách chuỗi
12
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ý, dùng thêm biến:
$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 của shell script khi thực thi
- Xem danh sách biến môi trường, lệnh: env
- Tạo thêm biến môi trường mới: export <var>=<value>
$1, $2, $3….: vị trí và nội dung của các tham số trên dòng lệnh, từ trái sang
phải
$*: danh sách 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 sách 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
13
Ví dụ:
$IFS=”^”
#tiếp nhận 3 tham số trên dòng lệnh là var1 var2 var3
$set var1 var2 var3
$echo “$@” => var1 var2 var3
$echo “$*” => var1^var2^var3
#đặt IFS về null, biến $* trả về danh sách thuần túy của các tham số
$unset IFS
$echo “$*” => var1 var2 var3
$echo “tham so thu 1 la $1” => var1
$echo “tham so thu 3 la $3” => var3
Biến $# sẽ chứa số tham số của lệnh, ở ví dụ trên ta có:
$echo “$#” => 3
14
4. Điều kiện Để kiểm tra điều kiện boolean: lệnh test hoặc [ ] test <condition> hoặc [ condition ] Ví dụ: kiểm tra xem file mang tên hello.c co tồn tại trong hệ thống không?
if test -f hello.c
then
…
fi
hoặc: if [ -f hello.c ]
then
….
fi
Lưu ý: đặt khoảng trắng giữa lệnh [] và biểu thức kiểm tra
15
Các kiểu so sánh:
So sánh chuỗi
s1 = s2 -> true nếu 2 chuỗi bằng nhau chính xác từng ký tự một
s1 != s2 -> true nếu 2 chuối không bằng nhau
-n s1 -> true nếu s1 không rỗng
-x s1 -> true nếu s1 rỗng
So sánh toán học
exp1 -eq exp2 -> true nếu hai biểu thức bằng nhau
exp1 -ne exp2 -> true nếu 2 biểu thức không bằng nhau
exp1 -gt exp2 -> true nếu exp1 lớn hơn exp2
exp1 -ge exp2 -> true nếu exp1 lớn hơn hay bằng exp2
exp1 -lt exp2 -> true nếu exp1 nhỏ hơn exp2
exp1 -le exp2 -> true nếu exp1 nhỏ hơn hay bằng exp2
! exp -> true nếu exp là false 16
Kiểm tra điều kiện tập tin
-d file -> true nếu file là thư mục
-e file -> true nếu file tồn tại trong đĩ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. (set-gid cho phép chương trình quyền của nhóm)
-r file -> true nếu file cho phép đọc
-s file -> true nếu kích thước file khác 0
-u file -> true nếu set-user-id được thiết lập trên file. (set-uid cho phép chương trình quyền của chủ sở hữu (owner) thay vì quyền của user thông thường)
-w file -> true nếu file cho phép ghi
-x file -> true nếu file được phép thực thi
Chú ý: khi dùng các điều kiện trên file phải tồn tại (trừ -f)
17
Tính toán trong Shell:
1. Sử dụng $((...))
ví dụ :
x=4
x=$x+5
echo $x
4+5
x=$(($x+5))
y=$(($x*2))
echo $x, $y
-> 9,18
# or: x=$((x+5))
# or: x=$(( x + 5 ))
# or: x=$((x + 5))
18
2. Sử dụng: `expr
ví dụ :
x=”12”
x=`expr $x + 1`
y=`expr $x \* 2`
echo $x, $y
->13, 26
3. Sử dụng: let
Ví dụ:
x=5
let x=$x+2
let y=$x*3
echo $x,$y
-> 7,21
# or: let x=x+2
1. Lệnh if
Cú pháp:
if condition
then
statements
else
statements
fi Ví dụ
2. Lệnh elif trong if Cho phép kiểm tra điều kiện lần thứ 2 bên trong else
if condition1
then
statements
elif condition2
statements
else
statements
fi Ví dụ 19
Vấn đề phát sinh với các biến nhận giá trị chuỗi:
Ví dụ:
if [ $answer = “yes” ].
Nếu ko nhập giá trị cho biến answer thì sẽ nhận thông báo lỗi:
[: =: unary operator expected
Vì: shell diễn dịch là:
if [ = “yes” ]
Để tránh lỗi này, ta nên bọc nội dung biến bằng dấu “ “:
if [ “$answer” = “yes” ].
Lúc đó, shell sẽ diễn dịch:
if [ “ “ = “yes” ]
Nếu là số thì ko cần
Nên bắt lỗi trong các trường hợp này.
20
3. Lệnh for
Sử dụng for để lặp lại một số lần với giá trị xác định
Cú pháp:
for variable in values
do
statements
done Ví dụ
Hoặc có pháp giống C (với Ub /bin/bash)
4. Lệnh while
While cho phép lặp vô hạn khi điều kiện kiểm tra vẫn còn đúng
Cú pháp:
while codition
do
statements
done
Ví dụ
21
5. Lệnh until
Cú pháp:
until codition
do
statements
done
Vòng lặp sẽ dừng lại khi điều kiện kiểm tra là đúng. Ví dụ 6. Lệnh case
Cú pháp:
case mau in
mau1)
cau_lenh;;
mau2)
cau_lenh;;
….
*)
cau_lenh ;;
Esac Ví dụ vd
22
Trong đó, mau được so sánh lần lượt với các mẫu mau1, mau2...
Nếu có một mẫu trùng khớp thì (các) câu lệnh tương ứng sẽ được thực hiện cho đến khi gặp hai dấu chấm phảy (;;).
Nếu không có mẫu nào trùng khớp thì (các) câu lệnh trong khối * được thực hiện.
Chú ý:
- Ký tự đại diện * cho phép so khớp với mọi loại chuỗi, nó thường được xem như trường hợp so sánh đúng cuối cùng nếu các mẫu so sánh trước đó thất bại.
- Muốn sử dụng nhiều mẫu trên một dòng so sánh của một lệnh case thì sử dụng dấu | để phân cách giữa các mẫu, ví dụ:
case “$answer” in
“yes” | “y” | “YES” | “Yes” ) echo “Good morning”;;
“no” | “No” ) echo “Good afternoon”;;
* ) echo “sorry, not found”;;
esac
23
1. Danh sách AND - &&
AND cho phép thực thi một chuỗi lệnh kề nhau, lệnh sau chỉ
thực hiện khi lệnh trước đã được thực thi xong và trả về mã lỗi
thành công.
Cú pháp: statements1 && sratements2 && ….
Kết quả trả về của AND sẽ là true nếu tất cả các lệnh được
thực hiện, ngược lại là false.
Ví dụ: vidu11.sh Ví dụ
Dùng lệnh touch file1 để kiểm tra file1 đã tồn tại hay chưa, nếu
chưa thì tạo mới, tiếp đến lệnh xóa file rm file2. Sau cùng dùng
danh sách AND để kiểm tra xem các file có đồng thời tồn tại
không để đưa thông báo thích hợp.
24
2. Danh sách OR - ||
Tương tự AND, OR cho phép thực thi một chuỗi lệnh kề nhau, nhưng
nếu có một lệnh trả về true thì việc thực thi dừng lại.
Cú pháp: statements1 || statements2 || ….
Kết quả trả về của OR sẽ là true nếu một trong các lệnh là true.
Lệnh && gọi lệnh tiếp theo khi các lệnh trước đó true
Kết hợp cả AND và OR, ta có thể xử lý được hầu hết mọi trường hợp
logic trong lập trình.
Ví dụ:
[ -f file1 ] && command_for_true || command_for_false
Đây là một cách viết ngắn gọn của if else Ví dụ
3. Khối lệnh {}
Trường hợp muốn thực thi một khối lệnh tại nơi chỉ cho phép đặt
một lệnh (như trong AND hay OR), ta sử dụng {} để bọc khối lệnh
vd 25
1. Cú pháp function_name () { statements } Ví dụ 2. Biến cục bộ và biến toàn cục Biến cục bộ: có hiệu lực trong hàm dùng từ khóa: local. Nếu không có từ khóa local thì các biến được xem là biến toàn cục. Biến toàn cục: Được nhìn thấy và có thể thay đổi bởi tất cả các hàm trong cùng script Nó có thể tồn tại và lưu giữ kết quả sau khi hàm chấm dứt. * Nếu biến cục bộ và toàn cục trùng tên thì biến cục bộ được ưu tiên và có hiệu lực đến khi hàm chấm dứt. Ví dụ
Hàm có thể trả về một giá trị số, dùng lệnh: return try_func() { return <gtri> }
26
Để trả về giá trị chuỗi, dùng lệnh echo và chuyển hướng nội dung
kết xuất của hàm khi gọi, ví dụ:
try_fun() {
echo “Sample text”
}
x=$(try_func)
biến x sẽ nhận trị trả về của hàm là “Sample text”.
$(function_name) là cách lấy về nội dung của một lệnh
Hoặc để lấy trị trả về của hàm, ta sử dụng biến toàn cục (do biến
toàn cục vẫn lưu lại giá trị ngay cả khi hàm chấm dứt).
27
3. Hàm và cách truyền tham số
Shell không có cách khai báo tham số cho hàm.
Ta truyền tham số cho các hàm tương tự như truyền tham số trên dòng lệnh.
Ví dụ, truyền tham số cho hàm funvd(), ta gọi hàm như sau:
funvd para1, para2,…..
Bên trong hàm, ta gọi các biến môi trường $*, $1, $2… chúng chính là các đối số truyền vào khi hàm được gọi.
Lưu ý, nội dung của $*, $1, $2…do biến môi trường nắm giữ sẽ được shell tạm thời cất đi.
Một khi hàm chấm dứt, các giá trị sẽ được khôi phục lại.
Ví dụ 15
28
Ex, Viết hàm tìm max 2 số
Dùng hàm để tìm max 4 số
max2so()
{
if [ $1 –gt $2 ]
then
m=$1
else
m=$2
fi
echo $m
return $m
}
#Main
max=$1
for i in $*
do
max=$(max2so $max $i)
done
echo “Max 4 so: $max”
exit 0
29
1. Mảng
a. Khai báo: (không cần phải khai báo)
array[xx]
Có thể khai báo mảng bằng lệnh declare –a array
- Phần tử của mảng mặc định bắt đầu từ chỉ số 0
b. Gán giá trị cho mảng:
array=( zero one two three four )
Hoặc:
array[0]=zero ; array[4]=four
Hoặc:
Array=( [xx]=XXX [yy]=YYY ...)
Hoặc :
array[5]=`expr ${array[11]} + ${array[13]}`
30
c. Lấy giá trị mảng/:
${array[xx]}
Ví dụ: array=( zero one two three four five )
echo ${array[0]} # zero
echo ${array:0} # zero
echo ${array[3]} # three
echo ${array:1} # ero : lấy từ vị trí số 1 của phần tử thứ hai
echo ${array[2]:1:2] # wo: lấy từ vị trí số 1 đi 2 kí tự của phần tử thứ ba
31
c. Lấy giá trị mảng : ${array[xx]}
- Lấy tất cả phần tử mảng:
${array[@]} hoặc ${array[*]}
Vd: array=( one two three four five )
echo ${array[@]} # one two three four five: tất cả
echo ${array[@]:0} # one two three four five: tất cả
- Lấy một số phần tử trong mảng:
echo ${array[@]:1} # two three four five: lấy từ pt thứ 2
echo ${arrayZ[@]:1:2} # two three : lấy từ phần tử thứ 2 đi 2 pt
32
33
d. Chiều dài mảng/1 phần tử mảng:
${#array[@]} hoăc ${#array[*]}
Ví dụ: array=( zero one two three four five )
echo ${#array[0]} # 4 : chiều dài của phần tử thứ nhất
echo ${#array} # 4
echo ${#array[1]} # 3 : chiều dài của phần tử thứ 2
echo ${#array[*]} # 6 : Số phần tử của mảng
echo ${#array[@]} # 6 : Số phần tử của mảng.
e. Xoá mảng : dùng lệnh unset
Ví dụ:
unset array[1] : xóa phần tử thứ 2 của mảng array
unset array : xóa toàn bộ mảng array
f. Khai báo mảng rỗng
array1=( ' ' ) # mảng array1 có một phần tử rỗng.
array2=( ) # mảng array2 rỗng
34
g. Nới rộng mảng: Khai báo thêm phần tử vào mảng
Ví dụ:
array0=( "${array0[@]}" "new1" )
# ${array0[@]} là mảng cũ, new1 là phần tử mới
hoăc
array0[${#array0[*]}]="new2"
# ${array0[@]} là mảng cũ, new2 là phần tử mới
h. Chép mảng
Ví dụ:
array2=( "${array1[@]}" )
# sao chép mảng array 2 giống mảng array1
hoặc: array2="${array1[@]}"
35
echo "nhap so pt mảng"
read n
for (( i=1; i <= $n;
i++ ))
do
echo –n "pt thu $i"
read a[i]
done
echo "mang la: ${a[@]}"
Dc=0
Dl=0
T=0
for (( i=1; i <= $n;
i++ ))
do
if [ `expr ${a[i]} % 2`
-eq 0 ]
then
Dc=`expr $Dc + 1`
else
Dl=`expr $Dl + 1`
fi
T=`expr $T + ${a[i]}`
done
echo "Co $Dc so chan.
Co $Dl so le. Tong la
$T"
exit 0
2. Chuỗi
a. Chiều dài chuỗi :
${#string} hoặc expr
Ví dụ: stringZ=abcABC123ABCabc
echo ${#stringZ} # 15
echo `expr length $stringZ` # 15
echo `expr "$stringZ" : '.*'` # 15
b. Vị trí chuỗi con:
expr index $string $substring
Ví dụ :
stringZ=abcABC123ABCabc
echo `expr index "$stringZ" C12` # 6 : C vị trí C
echo `expr index "$stringZ" c` # 3 : vị trí c
36
c. Lấy chuỗi con : ${string:position}
Lấy chuỗi con của chuỗi String bắt đầu từ vị trí position kể từ đầu chuỗi bên trái
${string:position:length} : Lấy length kí tự của chuỗi string từ vị trí position
Ví dụ: stringZ=abcABC123ABCabc
# 0123456789..... index tính từ 0
echo ${stringZ:0} # abcABC123ABCabc
echo ${stringZ:1} # bcABC123ABCabc
echo ${stringZ:7} # 23ABCabc
echo ${stringZ:7:3} # 23A : lấy 3 kí tự từ vị trí thứ 7
Có thể lấy từ cuối chuỗi (từ bên phải chuỗi).
Ví dụ:
echo ${stringZ:-4} # abcABC123ABCabc :Không hoạt động
echo ${stringZ:(-4)} # Cabc, dùng dấu ngoặc
echo ${stringZ: -4} # Cabc, dùng khoảng trắng sau dấu : 37
Cách khác:
expr substr $string $position $length
Lấy length kí tự của chuỗi string từ vị trí position. Ví dụ:
stringZ=abcABC123ABCabc
# 123456789...... Index tin h tư 1
echo `expr substr $stringZ 1 2` # ab
echo `expr substr $stringZ 3 4` # ABC1
38
d. Xoá chuôi con
Xóa chuỗi substring ngắn nhất tính từ đầu chuỗi khỏi chuỗi string”
${string#substring}
Xóa chuỗi substring dài nhất tính từ đầu chuỗi khỏi chuỗi string
${string##substring}
Ví dụ:
stringZ=abcABC123ABCabc
# |--------|
# |-------------------|
echo ${stringZ#a*C} # 123ABCabc
echo ${stringZ##a*C} # abc
Xóa chuỗi như trên nhưng tính từ cuối chuỗi:
${string%substring} và ${string%%substring}
Ví dụ:
stringZ=abcABC123ABCabc
#|-|
# |----------------|
echo ${stringZ%b*c} # abcABC123ABCa
echo ${stringZ%%b*c} # a 39
1. Nhóm lệnh thực hiện trong chương trình: a. break, b. continue, c. : (rỗng) 2. Nhóm lệnh thực thi chương trình: a. . (Thực thi), b. exec, c. exit, d. export, e. trap 3. Nhóm lệnh về toán học: a. eval, b. expr, c. return, d. printf 4. Nhóm lệnh về biến: a. set, b. shift, c. unset
40
1. Nhóm lệnh thực hiện trong chương trình: a. Break Để thoát khỏi vòng lặp for, while, until bất kể điều kiện của các lệnh này có diễn ra hay không. vd b. Continue Thường được dùng bên trong vòng lặp, Nó yêu cầu vòng lặp quay lại thực hiện bước lặp kế tiếp mà không cần thực thi các khối lệnh còn lại. vd c. Lệnh : (rỗng) - (null command). Đôi lúc lệnh này được dùng với ý nghĩa logic là true. Khi dùng lệnh : việc thực thi nhanh hơn việc so sánh true. Ví dụ while : sẽ tương đương với while true. vd
41
2. Nhóm lệnh thực thi chương trình:
a. Lệnh . (thực thi)
- Dùng để gọi thực thi một script trong shell hiện hành.
ý nghĩa: là nó thi hành và giữ nguyên những thay đổi về mội trường mà script tác động.
Cú pháp: . ./shell_script
b. exec
- Dùng gọi một lệnh bên ngoài khác. Thường gọi một shell phụ khác
c. exit n
- Lệnh exit sẽ thoát khỏi shell nào đó và trả về mã lỗi n. Trong các script, nó trả về mã lỗi cho biết script được thực thi thành công hay ko.
- Mã lỗi 0 có nghĩa là thành công. Các giá trị khác:
từ 1-125 có ý nghĩa với các mục đích khác nhau
126: file không thể thực thi
127: Lệnh không tìm thấy
>128: nhận được tín hiệu phát sinh.
- Sử dụng exit trên dòng lệnh thì sẽ thoát khỏi shell chính và trở về màn hình login.
42
d. export Lệnh export có tác dụng khai báo biến toàn cục (biến môi trường). Khi bắt đầu thực thi 1 shell, các biến môi trường đều được lưu lại. Biến khai báo trong script: có giá trị đối với shell triệu gọi script đó. Biến khai báo bằng lệnh export : thấy được ở tất cả các script trong các shell khác
#!/bin/sh foo="This is foo" export bar="This is bar” # biến khai báo export echo "Value: $foo" echo "Value: $bar“ Kết quả: Value: This is foo #gtrị biến trong script Value: This isbar # gtri biến khai báo=export
43
e. trap dùng để bẫy một tín hiệu do hệ thống gửi đến shell trong quá trình thực thi script. Tín hiệu thường là 1 thông điệp của hệ thống gửi đến chương trình yêu cầu hay thông báo về công việc nào đó mà hệ thống sẽ t. hiện. Với Script, trap giúp ta đón bắt và xử lý một số tín hiệu rất thường xảy ra Cú pháp: trap command signal Lưu ý: command yêu cầu trap thực hiện được đặt trong dấu „ „ để giải hoặc vô hiệu hóa lệnh trap trước đó, ta thay command bằng dấu – Các tín hiệu: HUP (1) -> Hang-up, nhận được khi người dùng logout INT (2) -> Interrupt, tín hiệu ngắt khi người dùng nhấn ^C QUIT (3) -> Quit, nhận được khi nhấn Ctrl-\ ABRT (6) -> Abort, tín hiệu chấm dứt, nhận khi timeout ALRM (14) -> Alarm, t. báo được dùng xử lý cho tình huống timeout TERM (15) -> terminate, nhận được khi hệ thống y. cầu shutdown
44
3. Nhóm lệnh về toán học: eval, expr, return, printf
a. eval
Lệnh eval cho phép bạn ước lượng một biểu thức chứa biến
vd
b. expr
Lệnh expr ước lệ giá trị đối số truyền cho nó như là một biểu thức. Thường expr được dùng trong việc tính toán các kết quả toán học đổi giá trị từ chuỗi sang số.
Ví dụ:
x=”12”
x=`expr $x + 1` => kết quả là 13
- Chú ý: Cặp dấu ` ` bọc biểu thức expr. Các toán tử và toán hạng phải cách nhau bằng khoảng trắng
- Sau đây là một số biểu thức ước lượng mà expr cho phép:
expr1 | expr2 -> Kết quả là expr1 nếu expr1 khác 0 ngược lại là expr2
expr1 & expr2 -> 0 nếu một trong 2 biểu thức là zero ngược lại kết quả là expr1
45
expr1 = expr2 -> bằng
expr1 > expr2 -> lớn hơn
expr1 >= expr2 -> lớn hơn hoặc bằng
expr1 < expr2 -> nhỏ hơn
expr1 <= expr2 -> nhỏ hơn hoặc bằng
expr1 != expr2 -> không bằng
expr1 + expr2 -> cộng
expr1 - expr2 -> trừ
expr1 * expr2 -> nhân
expr1 / expr2 -> chia
expr1 % expr2 -> chia dư module
Các shell sau này, lệnh expr được thay thế bằng cú pháp $((...))
ví dụ :
z=$((z+3))
z=$(($m*$n))
vi du:
46
c. return
Lệnh return dùng để trả về giá trị của hàm. Lệnh không có tham số sẽ trả về mã lỗi của lệnh vừa thực hiện sau cùng.
d. printf
Cho phép in một chuỗi ra màn hình. Lệnh này không hỗ trợ định dạng số có dấu chấm động (float) bởi các tính toán của shell đều dựa trên số nguyên.
Sau đây là danh sách các ký tự đặc biệt có thể sử dụng với dấu \, chúng được gọi là các chuỗi thoát:
\\ -> cho phép hiện thị ký tự \ trong chuỗi
\a -> phát tiếng chuông bip
\b -> ký tự xóa backspace
\f -> đẩy dòng
\n -> sang dòng mới
\r -> về đầu dòng
\t -> canh tab ngang
\v -> canh tab dọc
47
Định dạng số và chuỗi bằng ký tự %, bao gồm:
d -> số nguyên
c -> ký tự
s -> chuỗi
% -> hiện thị ký hiệu %
Ví dụ:
$printf “Your name %s. It is nice to meet you \n” Van An
Your name Van An. It is nice to meet you
$printf “%s %d \t %s” “Hi there” 10 “people”
Hi there 15 people
Lệnh printf thường được dùng thay thế echo, mục đích để in chuỗi không sang dòng mới (printf chỉ sang dòng mới khi dùng \n).
48
4. Nhóm lệnh về biến: set, shift, unset
a. set
Lệnh set dùng để áp đặt giá trị cho các tham số môi trường như $1, $2, $3… Lệnh set loại bỏ các khoảng trống không cần thiết và đặt nội dung của chuỗi truyền cho nó vào các biến tham số.
Ví dụ:
$set anh binh canh
$echo $1
anh
$echo $3
canh
49
b. shift
Lệnh shift di chuyển nội dung tất cả các tham số môi trường $1, $2, $3… xuống một vị trí. Bởi vì hầu như ta chỉ dùng được tối đa 9 tham số từ $1 đến $9, tham số từ $10 trở lên sẽ được dùng bằng lệnh shift ($10 thường được hiểu là $1 và „0‟).
Ví dụ: try_shift.sh
$! /bin/sh
while [ “$1” !=” “ ]; do
echo “$1”
shift
done
exit 0
Chạy chương trình: ./try_shift.sh xin chao ban 1 2
Kết qủa:
xin
chao
ban
1
2 50
c. unset
Lệnh unset dùng để loại bỏ biến khỏi môi trường shell.
Ví dụ:
#! /bin/sh
bien=”Hello Hello”
echo $bien
unset bien
echo $bien
51
Cú pháp: $(command) hoặc `command
Ví dụ:
echo thu muc hien thoi la $PWD
echo no chua $(ls -a) file
Lệnh $( ) rất mạnh và sử dụng phổ biến trong lập trình shell cho Linux.
Ta có thể lấy kết quả của $( ) làm đối số truyền tiếp cho các lệnh khác.
52
- Tương tự lập trình Shell, ta cũng cũng dùng một trình soạn thảo để soạn thảo chương trình theo ngôn ngữ C. Đặt tên tệp với đuôi *.c.
- Sau đó ta cần biên dịch chương trình *.c này: cc/gcc [-o outputfile] file.c
- Mặc định output file sẽ là một file executable tên là a.out.
- Tạo ra file executable khác, dùng -o file_name
- Chạy chương trình: ./a.out
Ví dụ: hello.c
#include <stdio.h>
main() {
printf("Xin chao C!\n");
}
Biên dịch và chạy chương trình hello.c như sau:
$ cc hello.c
$ ./a.out
hoặc $ cc -o hello hello.c
$ ./hello 53
# if…. Then….fi
#! /bin/sh
echo Are you John?
read answer
if [ $answer = yes ]
then
echo Hello $answer
else
echo Sorry
exit 1
fi
exit 0
54
# Script to test if..elif...else- number a
read var
if [ "$var" -gt 0 ]
then
echo $var is positive
elif [ "$var" -lt 0 ]
then
echo $var is negative
elif [ "$var" -eq 0 ]
then
echo $var is zero
else
echo Opps! $var is not number, give
number
fi
exit 0
55
# For…do…done: sum 1+2+…+n
#! /bin/sh
read n
s=0
for (( i = 1; i <= $n; i++ ))
do
let s=s+i
done
echo “tong la: $s”
exit 0
# print column – row 1-5
#!/bin/bash
for (( i = 1; i <= 5; i++ )) ### Outer FOR
do
for (( j = 1 ; j <= 5; j++ )) ### Inner for
do
echo -n "$i "
done
echo "" #### print the new line ###
done
56
for i in a b c d e f do echo i done don
#While… do… done:view number
#! /bin/sh
t=0
X=1
While (( X <=10 )) # while [ $x –le 10 ]
do
Echo “hello X is : $X“
Let t=t+1
Done
# view files
#! /bin/sh
reply=y
while test "$reply" != "n"
do
echo –n "Enter file name?"
read fname
cat ${fname}
echo –n "wish to see more files :"
read reply
Done
57
#Until…. Do… done
#! /bin/sh
var=10
until [ $var -eq 0 ]
do
echo -n " $var "
var=`expr $var - 1`
echo
Done
58
# view users loging
#! /bin/sh
echo “locate for user “
until who | grep “$1” > /dev/null
do
sleep 60
done
#in ra chuong
echo –e \\a
# Hien thi ten user da login
echo “*********$1 has just logged in***********”
exit 0 Chương trình thực hiện: Lệnh who lọc ra danh sách các user đăng nhập vào hệ thống. Nó chuyển danh sách này cho grep bằng cơ chế đường ống (|). Lệnh grep lọc ra tên user theo biến môi trường $1 hiện có nội dung là chuỗi “tên user”. Một khi lệnh grep lọc ra được dữ liệu, nó sẽ chuyển ra vùng tập tin rỗng /dev/null và trả về giá trị true, lệnh until kết thúc.
59
# Case .. In .. esac
#! /bin/sh
echo “Is it morning?”
read answer
case “$answer” in
“yes”) echo “Good morning”;;
“no”) echo “Good afternoon”;;
* ) echo “sorry, not found”;;
esac
exit 0
60
#! /bin/sh
while true
do
echo "Enter choice"
echo "(press 'q' to exit)"
echo "1 date 2 who"
echo "3 ls 4 pwd"
read choice
case $choice in
1)date;;
2)who;;
3)ls -la;;
4)pwd;;
q)break;;
*)echo "That was not one of the
choices";;
esac
done
61
#! /bin/sh
touch file1
rm –f file2
if [ -f file1 ] && echo “hello” && [ -f file2 ]
&& echo “there”
then
echo –e “in if”
else
echo –e “in else”
fi
exit 0
62
#! /bin/sh
rm –f file1
if [ -f file1 ] || echo “hello” || echo “there”
then
echo “in if”
else
echo “in else”
fi
exit 0
Khối lệnh:
if [ -f file1 ] && {
ls -l
echo "Khoi lenh"
}
then
echo "Lenh hoan thanh"
fi
63
# function
#! /bin/sh
try_func () {
echo “2. Function is executing”
}
echo “1. Script vidu starting”
try_func
echo “3. Script vidu ended”
exit 0
64
# function_ variable
# /bin/sh
name_var="global variable"
try_func() {
local name_var="local varable"
echo "Function is executing"
echo $name_var
}
echo "Script starting"
echo $name_var
try_func
echo "Script ended"
echo $name_var
exit 0
65
#! /bin/sh
ask() {
echo “ Bien trong ham la $*”
echo “Bien 1 $1 va bien 2 $2”
while true; do
echo -n “Nhap yes or no”
read x
case “$x” in
y | yes) return 0;;
n | no) return 1;;
*) echo “Tra loi yes or no”
esac
done
}
echo “Bien goc la $*”
if ask “Your name” “$1?”
then
echo “Hi $1”
else
echo “Sorry”
fi
exit 0
Thực thi: ./vidu15.sh Anh Ba
66
#!/bin/sh
rm -rf fred*
echo > fred1
echo > fred2
mkdir fred3
echo > fred4
for file in fred*
do
if [ -d "$file" ]; then
echo $file
break
echo “hello”
fi
done
echo "first directory fred was $file"
exit 0
Kq:
fred3
first directory fred was fred3
67
#!/bin/sh
rm -rf fred*
echo > fred1
echo > fred2
mkdir fred3
echo > fred4
for file in fred*
do
if [ -d "$file" ]; then
continue
fi
echo "file is $file"
done
exit 0
68
#!/bin/sh
rm -f fred
if [ -f fred ]
then
:
else
echo "file fred does not exist"
fi
exit 0
69
foo=10
x=foo
y='$'$x
echo $y
######
foo=10
x=foo
eval y='$'$x
echo $y
In ra kết quả là chuỗi $foo
In ra kết quả là 10
70