70
1

Chuong 3 - Lap Trinh Shell

Embed Size (px)

Citation preview

Page 1: Chuong 3 - Lap Trinh Shell

1

Page 2: Chuong 3 - Lap Trinh Shell

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

Page 3: Chuong 3 - Lap Trinh 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

Page 4: Chuong 3 - Lap Trinh Shell

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

Page 5: Chuong 3 - Lap Trinh Shell

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

Page 6: Chuong 3 - Lap Trinh Shell

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

Page 7: Chuong 3 - Lap Trinh Shell

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

Page 8: Chuong 3 - Lap Trinh Shell

Đặ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

Page 9: Chuong 3 - Lap Trinh Shell

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

Page 10: Chuong 3 - Lap Trinh Shell

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

Page 11: Chuong 3 - Lap Trinh Shell

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

Page 12: Chuong 3 - Lap Trinh Shell

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

Page 13: Chuong 3 - Lap Trinh Shell

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

Page 14: Chuong 3 - Lap Trinh Shell

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

Page 15: Chuong 3 - Lap Trinh Shell

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

Page 16: Chuong 3 - Lap Trinh Shell

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

Page 17: Chuong 3 - Lap Trinh Shell

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

Page 18: Chuong 3 - Lap Trinh Shell

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

Page 19: Chuong 3 - Lap Trinh Shell

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

Page 20: Chuong 3 - Lap Trinh Shell

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

Page 21: Chuong 3 - Lap Trinh Shell

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

Page 22: Chuong 3 - Lap Trinh Shell

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.

Page 23: Chuong 3 - Lap Trinh Shell

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

Page 24: Chuong 3 - Lap Trinh Shell

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

Page 25: Chuong 3 - Lap Trinh Shell

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

Page 26: Chuong 3 - Lap Trinh Shell

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

Page 27: Chuong 3 - Lap Trinh Shell

Để 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

Page 28: Chuong 3 - Lap Trinh Shell

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

Page 29: Chuong 3 - Lap Trinh Shell

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

Page 30: Chuong 3 - Lap Trinh Shell

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

Page 31: Chuong 3 - Lap Trinh Shell

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

Page 32: Chuong 3 - Lap Trinh Shell

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

Page 33: Chuong 3 - Lap Trinh Shell

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

Page 34: Chuong 3 - Lap Trinh Shell

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[@]}"

Page 35: Chuong 3 - Lap Trinh Shell

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

Page 36: Chuong 3 - Lap Trinh Shell

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

Page 37: Chuong 3 - Lap Trinh Shell

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

Page 38: Chuong 3 - Lap Trinh Shell

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

Page 39: Chuong 3 - Lap Trinh Shell

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

Page 40: Chuong 3 - Lap Trinh Shell

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

Page 41: Chuong 3 - Lap Trinh Shell

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

Page 42: Chuong 3 - Lap Trinh Shell

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

Page 43: Chuong 3 - Lap Trinh Shell

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

Page 44: Chuong 3 - Lap Trinh Shell

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

Page 45: Chuong 3 - Lap Trinh Shell

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

Page 46: Chuong 3 - Lap Trinh Shell

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

Page 47: Chuong 3 - Lap Trinh Shell

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

Page 48: Chuong 3 - Lap Trinh Shell

Đị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

Page 49: Chuong 3 - Lap Trinh Shell

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

Page 50: Chuong 3 - Lap Trinh Shell

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

Page 51: Chuong 3 - Lap Trinh Shell

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

Page 52: Chuong 3 - Lap Trinh Shell

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

Page 53: Chuong 3 - Lap Trinh Shell

- 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

Page 54: Chuong 3 - Lap Trinh Shell

# 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

Page 55: Chuong 3 - Lap Trinh Shell

# 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

Page 56: Chuong 3 - Lap Trinh Shell

# 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

Page 57: Chuong 3 - Lap Trinh Shell

#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

Page 58: Chuong 3 - Lap Trinh Shell

#Until…. Do… done

#! /bin/sh

var=10

until [ $var -eq 0 ]

do

echo -n " $var "

var=`expr $var - 1`

echo

Done

58

Page 59: Chuong 3 - Lap Trinh Shell

# 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

Page 60: Chuong 3 - Lap Trinh Shell

# 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

Page 61: Chuong 3 - Lap Trinh Shell

#! /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

Page 62: Chuong 3 - Lap Trinh Shell

#! /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

Page 63: Chuong 3 - Lap Trinh Shell

#! /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

Page 64: Chuong 3 - Lap Trinh Shell

# 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

Page 65: Chuong 3 - Lap Trinh Shell

# 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

Page 66: Chuong 3 - Lap Trinh Shell

#! /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

Page 67: Chuong 3 - Lap Trinh Shell

#!/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

Page 68: Chuong 3 - Lap Trinh Shell

#!/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

Page 69: Chuong 3 - Lap Trinh Shell

#!/bin/sh

rm -f fred

if [ -f fred ]

then

:

else

echo "file fred does not exist"

fi

exit 0

69

Page 70: Chuong 3 - Lap Trinh Shell

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