Điều khiển luồng trong Shell

Trong khi viết một Shell script, có thể có một tình huống khi bạn cần để theo một path ngoài 2 path đã được cung cấp. Vì thế bạn cần tạo cách sử dụng của các lệnh có điều kiện mà cho phép chương trình của bạn tạo các quyết định chính xác và thực hiện các hành động đúng.

Unix Shell hỗ trợ các lệnh có điều kiện mà được sử dụng để thực hiện các hành động khác nhau dựa trên các điều kiện đa dạng. Tại đây chúng ta sẽ giải thích hai lệnh điều khiển luồng:

  • Lệnh if...else
  • Lệnh case...esac

Lệnh if…else trong Unix/Linux

Lệnh này là một lệnh điều khiển luồng hữu ích, được sử dụng để lựa chọn một tùy chọn từ một tập hợp tùy chọn đã cho.

Unix Shell hỗ trợ các mẫu lệnh if…else sau:

  • Lệnh if...fi trong Shell
  • Lệnh if…fi là lệnh điều khiển nền tảng mà cho phép Shell tạo các quyết định và thực thi các lệnh tùy theo điều kiện.

Cú pháp trong Unix/Linux

if [ bieuThuc ]
then
   cac lenh de thuc thi neu bieuThuc la true
fi

Ở đây, bieuThuc – biểu thức được tính toán. Nếu giá trị kết quả là true, các lệnh đã cho được thực hiện. Nếu expression là false thì khi đó các Lệnh sẽ không được thực hiện. Hầu hết mọi lần, bạn sẽ sử dụng các toán tử so sánh trong khi điều khiển luồng.

Bạn nên chú ý các khoảng trống giữa dấu ngoặc vuông và bieuThuc. Khoảng trống này là bắt buộc, nếu không có thì cú pháp của bạn sẽ bị lỗi.

Nếu bieuThuc là một lệnh shell, thì khi đó nó sẽ được cho là true nếu nó trả về giá trị 0 sau khi thực hiện. Nếu nó là một biểu thức logic, thì sau đó nó sẽ là true nếu nó trả về true.

Ví dụ trong Unix/Linux

#!/bin/sh
a=10
b=20
if [ $a == $b ]
then
   echo "a is equal to b"
fi
if [ $a != $b ]
then
   echo "a is not equal to b"
fi

Đoạn script trên sẽ cho kết quả sau:

a is not equal to b

Lệnh if…else…fi trong Shell

Lệnh if…else…fi là một mẫu lệnh điều khiển tiếp theo mà cho phép Shell thực thi các lệnh trong cách được kiểm soát hơn và điều khiển luồng giữa hai lựa chọn.

Cú pháp trong Unix/Linux

if [ bieuThuc ]
then
   cac lenh de thuc thi neu bieuThuc la true
else
   cac lenh de thuc thi neu bieuThuc la khong true
fi

Ở đây, biểu thức bieuThuc được ước lượng. Nếu giá trị kết quả là true, các lệnh đã cho được thực thi. Nếu bieuThuc là false, thì khi đó các lệnh sẽ không được thực hiện.

Ví dụ trong Unix/Linux

Chúng ta viết lại ví dụ trong chương về lệnh if…else theo cách tốt hơn bởi sử dụng lệnh if…else…fi như sau:

#!/bin/sh
a=10
b=20
if [ $a == $b ]
then
   echo "a is equal to b"
else
   echo "a is not equal to b"
fi

Nó sẽ cho kết quả sau:

a is not equal to b

Lệnh if…elif…fi trong Shell

Lệnh if…elif…fi là một mẫu lệnh điều khiển nâng cao mà cho phép Shell đưa ra quyết định chính xác theo một số các điều kiện.

Cú pháp trong Unix/Linux

if [ bieuThuc 1 ]
then
   cac lenh de thuc thi neu bieuThuc 1 la true
elif [ bieuThuc 2 ]
then
   cac lenh de thuc thi neu bieuThuc 2 la true
elif [ bieuThuc 3 ]
then
   cac lenh de thuc thi neu bieuThuc 3 la true
else
   cac lenh de thuc thi neu khong co bieuThuc nao la true
fi

Không có gì đặc biệt về đoạn code này. Nó là một chuỗi các lệnh if, mà mỗi lệnh if là một phần của mệnh đề else của lệnh trước. Ở đây, các lệnh được thực thi dựa trên cơ sở điều kiện true, nếu không có điều kiện nào là true, thì khi đó khối else được thực hiện.

Ví dụ trong Unix/Linux

#!/bin/sh
a=10
b=20
if [ $a == $b ]
then
   echo "a is equal to b"
elif [ $a -gt $b ]
then
   echo "a is greater than b"
elif [ $a -lt $b ]
then
   echo "a is less than b"
else
   echo "None of the condition met"
fi

Nó sẽ cho kết quả là:

a is less than b

Hầu hết các lệnh if kiểm tra mối quan hệ bằng cách sử dụng các toán tử quan hệ được đề cập trong chương trước.

Lệnh case...esac trong Unix/Linux

Bạn có thể sử dụng nhiều lệnh if…elif để thực hiện một nhánh có nhiều lựa chọn. Tuy nhiên, đây không là giải pháp tốt nhất, đặc biệt khi tất cả các nhánh phụ thuộc vào giá trị của một biến đơn.

Unix shell hỗ trợ lệnh case...esac mà giải quyết chính xác tình huống này, và nó thực hiện theo cách hiệu quả hơn là lặp lại sử dụng nhiều lệnh if…elif.

Bạn có thể sử dụng nhiều lệnh if…elif để thực hiện nhiều nhánh lựa chọn. Tuy nhiên, nó luôn luôn không phải là giải pháp tốt nhất, đặc biệt khi tất cả các nhánh phụ thuộc vào giá trị của một biến đơn.

Shell hỗ trợ lệnh case…esac mà xử lý tình huống này một cách chính xác, và nó thực hiện một cách hiệu quả hơn là việc lặp đi lặp lại các lệnh if…elif.

Cú pháp trong Unix/Linux

Cú pháp đơn giản của lệnh case…esac là cung cấp một biểu thức để ước lượng và một số lệnh khác nhau để thực thi dựa trên cơ sở giá trị của biểu thức.

Bộ phiên dịch kiểm tra mỗi case – trường hợp ứng với giá trị của biểu thức tới khi tìm thấy sự so khớp. Nếu không có sự so khớp, điều kiện mặc định sẽ được sử dụng.

case word in
  pattern1)
     cac lenh de thuc thi neu ket noi voi pattern1
     ;;
  pattern2)
     cac lenh de thuc thi neu ket noi voi pattern2
     ;;
  pattern3)
     cac lenh de thuc thi neu ket noi voi pattern3
     ;;
esac

Ở đây, chuỗi word được so sánh với mỗi pattern cho tới khi tìm thấy một sự so khớp. Các lệnh theo sau pattern được so khớp này thực hiện. Nếu không tìm thấy sự so khớp nào, lệnh case thoát ra mà không thực hiện bất kỳ hành động nào.

Sẽ không giới hạn số lượng các pattern, nhưng số lượng tối thiểu là 1.

Khi các phần lệnh thực thi, lệnh ;; chỉ dẫn rằng dòng chương trình nên nhảy tới phần cuối của lệnh case. Nó tương tự như lệnh break trong Ngôn ngữ chương trình C.

Ví dụ trong Unix/Linux

#!/bin/sh
FRUIT="kiwi"
case "$FRUIT" in
   "apple") echo "Apple pie is quite tasty." 
   ;;
   "banana") echo "I like banana nut bread." 
   ;;
   "kiwi") echo "New Zealand is famous for kiwi." 
   ;;
esac

Nó sẽ cho kết quả sau:

New Zealand is famous for kiwi.

Một cách sử dụng tốt cho một lệnh case là sự ước lượng các tham số dòng lệnh như sau:

#!/bin/sh
option="1" 
case  in 
   -f) FILE="2" 
      echo "File name is $FILE"
      ;; 
   -d) DIR="2" 
      echo "Dir name is $DIR"
      ;; 
   *)  
      echo "`basename 0`:usage: [-f file] | [-d directory]" 
      exit 1 # Command to come out of the program with status 1
      ;; 
esac 

Dưới đây là kết quả mẫu của chương trình này.

$./test.sh
test.sh: usage: [ -f filename ] | [ -d directory ]
$ ./test.sh -f index.jsp
$ vi test.sh
$ ./test.sh -f index.jsp
File name is index.jsp
$ ./test.sh -d unix
Dir name is unix
$

Lệnh case...esac của Unix Shell là tương tự với lệnh switch...case mà chúng ta có trong các chương trình C hoặc C++ và PERL etc.


Bình luận