Học bằng cách đọc theo thứ tự

Shell Script - Câu lệnh điều kiện

Kiểm tra tệp, chuỗi và số bằng [ -f config.txt ], [ -z "$name" ] và [ "$count" -lt 5 ], rẽ nhánh bằng if / elif / else, và định tuyến nhiều mẫu bằng case — viết và chạy từng script, minh họa trên terminal trong trình duyệt.

Rẽ nhánh bằng cách so sánh giá trị — so sánh chuỗi và số

Trong shell script, bạn thay đổi cái được chạy bằng cách kiểm tra xem chuỗi có khớp không hoặc số có lớn hơn không.

Để kiểm tra, bạn dùng lệnh test, hoặc [ ... ] cũng cho kết quả tương tự.

[] cần khoảng trắng ngay bên trong, nên bạn viết [ "$count" -lt 5 ].

Kiểm tra đúng trả về exit code 0, còn sai trả về 1.

So sánh chuỗi bằng = (bằng) và != (khác), và kiểm tra rỗng bằng -z (rỗng) hoặc -n (không rỗng).

So sánh số bằng -eq (bằng), -ne (khác), -lt (nhỏ hơn) và -gt (lớn hơn), và lưu ý rằng chuỗi và số dùng toán tử khác nhau.

Hãy bọc biến trong nháy kép như [ -z "$name" ] — như vậy cú pháp vẫn hợp lệ ngay cả khi giá trị rỗng.

count=3
mode="dev"
[ "$count" -lt 5 ] && echo small    # 3 nhỏ hơn 5, nên small
[ "$count" -gt 0 ] && echo positive # lớn hơn 0, nên positive
[ "$mode" = "prod" ] || echo other  # không phải prod, nên other
[ -z "$mode" ] || echo has-mode     # không rỗng, nên has-mode
Từ so sánh đến rẽ nhánh
[ "$count" -lt 5 ]exit code 0exit code 1khối thenkhối elsenếu đúngnếu saiđúng (0)sai (1)
[ ... ] trả về exit code 0 khi đúng và 1 khi sai; if chạy then khi đúng và else khi sai.
SyntaxÝ nghĩaExample
[ "$a" = "$b" ]đúng nếu chuỗi a và b bằng nhau[ "$mode" = "prod" ]
[ "$a" != "$b" ]đúng nếu chuỗi a và b khác nhau[ "$mode" != "dev" ]
[ -z "$v" ]đúng nếu biến v rỗng[ -z "$name" ] && echo empty
[ -n "$v" ]đúng nếu biến v không rỗng[ -n "$name" ] && echo set
[ "$a" -eq N ]đúng nếu số a bằng N[ "$count" -eq 0 ]
[ "$a" -ne N ]đúng nếu số a khác N[ "$count" -ne 0 ]
[ "$a" -lt N ]đúng nếu số a nhỏ hơn N[ "$count" -lt 10 ]
[ "$a" -gt N ]đúng nếu số a lớn hơn N[ "$count" -gt 0 ]

Viết một script nhận một số và một chuỗi làm tham số rồi rẽ nhánh theo giá trị của chúng.

① Mở compare.sh bằng vi compare.sh, nhấn i để vào insert mode, và viết #!/bin/sh ở dòng đầu tiên.

② Nhận tham số đầu tiên $1 như một số, kiểm tra nó bằng -lt với một giá trị nào đó, và in ra thông báo khác nhau khi nó nhỏ hơn và khi không.

③ Tiếp theo nhận tham số thứ hai $2 như một chuỗi, kiểm tra nó bằng = với một từ nào đó, và in ra thông báo khác nhau khi khớp và khi không.

④ Nhấn Esc, lưu bằng :wq, thêm quyền thực thi, rồi chạy nó với các tham số như ./compare.sh 3 dev.

⑤ Đổi các tham số thành ./compare.sh 8 prod và xác nhận rằng nhánh được chọn thay đổi.

⑥ Nếu bạn chưa chắc nên viết gì, hãy sao chép nội dung trong bảng đáp án rồi dán vào insert mode của vi. (Chạy đúng để hiện phần giải thích.)

Linux console
0 / 3 đã hoàn thành
Loading Linux Terminal...

Kiểm tra tệp và thư mục — -f / -d

Trong một script, bạn thường kiểm tra xem tệp cấu hình có tồn tại hay thư mục đầu ra đã sẵn sàng chưa trước khi tiếp tục.

Kiểm tra tệp bằng -f (tồn tại tệp thường) và thư mục bằng -d (tồn tại một directory).

Khi bạn chỉ quan tâm có gì đó tồn tại bất kể loại nào, hãy dùng -e, và để kiểm tra nó không rỗng, hãy dùng -s.

Bạn viết các kiểm tra này với cùng [ ... ] như với chuỗi và số, truyền vào một đường dẫn như [ -f config.txt ].

Chúng trả về exit code 0 khi đúng và 1 khi sai, nên kết hợp với if hoặc && / || bạn có thể viết quá trình khởi tạo có thì dùng, không có thì tạo.

touch report.txt                  # tạo nguyên liệu
[ -f report.txt ] && echo exists  # tệp tồn tại, nên exists
[ -d report.txt ] || echo notdir  # không phải directory, nên notdir
mkdir logs                        # tạo thư mục
[ -d logs ] && echo hasdir        # directory tồn tại, nên hasdir
Các loại kiểm tra tệp
đường dẫn cầnkiểm tra[ -f path ][ -d path ][ -e path ]đúng nếu làtệp thườngđúng nếu làdirectoryđúng nếu tồntại bất kể loạiloại kiểm trađiều kiện để đúng
-f kiểm tra tệp thường, -d kiểm tra directory, và -e kiểm tra sự tồn tại bất kể loại nào. Cùng một đường dẫn có thể cho kết quả khác nhau tùy theo điều bạn hỏi.
SyntaxÝ nghĩaExample
[ -f f ]đúng nếu f tồn tại như một tệp thường[ -f config.txt ] && echo found
[ -d d ]đúng nếu d tồn tại như một directory[ -d logs ] && echo dir
[ -e p ]đúng nếu p tồn tại, bất kể loại nào[ -e data ] && echo there
[ -s f ]đúng nếu f tồn tại và không rỗng[ -s log.txt ] && echo nonempty

Viết một script kiểm tra rẽ nhánh theo việc một tệp và một thư mục có tồn tại hay không.

① Mở setup.sh bằng vi setup.sh, nhấn i để vào insert mode, và viết #!/bin/sh ở dòng đầu tiên.

② Kiểm tra tệp đích bằng [ -f ... ] và in ra rằng bạn dùng nó khi nó tồn tại, hoặc rằng bạn tạo một giá trị mặc định khi không.

③ Tiếp theo kiểm tra một thư mục log bằng [ -d ... ] và in ra thông báo cho mỗi trường hợp.

④ Nhấn Esc, lưu bằng :wq, rồi thêm quyền thực thi.

⑤ Chạy script và xác nhận kết quả kiểm tra được in ra.

⑥ Nếu bạn chưa chắc nên viết gì, hãy sao chép nội dung trong bảng đáp án rồi dán vào insert mode của vi.

Linux console
0 / 3 đã hoàn thành
Loading Linux Terminal...

Chia luồng xử lý — if / elif / else

if chạy khối then chỉ khi điều kiện đúng.

Để thử lần lượt nhiều điều kiện hãy dùng elif, cho trường hợp không cái nào khớp thì thêm else, và đóng lại bằng fi.

Ngăn cách các phần bằng dấu chấm phẩy như trong if condition; then action; fi, hoặc tách chúng ra nhiều dòng.

count=3
if [ "$count" -eq 0 ]; then
  echo "none"
elif [ "$count" -lt 5 ]; then
  echo "few ($count)"
else
  echo "many ($count)"
fi                              # in ra few (3)
Luồng if / elif / else
if [ A ]khối Aelif [ B ]khối Belsekhối dự phòngđúngsaiđúngsaikiểm tra từ trên xuốngchỉ chạy nhánh đúng đầu tiên
Bắt đầu từ if, nó thử từng điều kiện và chỉ chạy nhánh đầu tiên trở thành đúng. Nếu không cái nào đúng, nó chuyển sang else.
SyntaxÝ nghĩaExample
if cond; then … fichạy khi điều kiện đúngif [ -f f ]; then echo ok; fi
thenbắt đầu phần thân khi đúngif [ -f f ]; then echo ok; fi
elif cond; then …thử cái tiếp theo khi cái trước saielif [ "$n" -lt 5 ]; then …
else …chạy khi không cái nào đúngelse echo other; fi
fiđóng ifif …; then …; fi

Viết một script kiểm tra thay đổi thông báo dựa trên một số đếm.

① Mở check.sh bằng vi check.sh, nhấn i để vào insert mode, và viết #!/bin/sh ở dòng đầu tiên.

② Thiết lập một biến giữ một số, rồi dùng if / elif / else để in ra thông báo khác nhau cho -eq 0, cho -lt một giá trị nhỏ, và cho mọi trường hợp còn lại.

③ Nhấn Esc, lưu bằng :wq, rồi thêm quyền thực thi.

④ Chạy script và xác nhận nó chọn nhánh nào.

⑤ Nếu bạn chưa chắc nên viết gì, hãy sao chép nội dung trong bảng đáp án rồi dán vào insert mode của vi.

Linux console
0 / 3 đã hoàn thành
Loading Linux Terminal...

Định tuyến nhiều mẫu — case

Khi bạn so khớp một giá trị với nhiều ứng viên, case đọc rõ ràng hơn.

Nó có dạng case value in pattern) action ;; esac, trong đó bạn kết thúc mỗi mẫu bằng ;; và bắt trường hợp không khớp bằng *).

Nó làm cho ý định của việc rẽ nhánh rõ ràng hơn so với việc xếp chồng nhiều tầng if.

action="start"
case "$action" in
  start) echo "starting service" ;;
  stop)  echo "stopping service" ;;
  *)     echo "unknown action: $action" ;;
esac                            # in ra starting service
Định tuyến case
case "$action" instart)stop)*)start action ;;stop action ;;dự phòng ;;so khớp mẫuhành động khớp (;;)
case so khớp giá trị với các mẫu từ trên xuống, chỉ chạy nhánh khớp đầu tiên, và đóng lại bằng esac. *) là trường hợp không khớp.
SyntaxÝ nghĩaExample
case x in pat) … ;; esacđịnh tuyến một giá trị tới nhiều mẫucase "$1" in start) … ;; esac
pat)một mẫu được so khớp với giá trịstart) echo go ;;
;;kết thúc hành động của mỗi casestart) echo go ;;
*)trường hợp không khớp*) echo other ;;
esacđóng casecase x in …; esac

Viết một script điều khiển nhận một tên hành động làm tham số và định tuyến theo giá trị của nó.

① Mở service.sh bằng vi service.sh, nhấn i để vào insert mode, và viết #!/bin/sh ở dòng đầu tiên.

② Nhận tham số đầu tiên $1 làm tên hành động, và dùng case định tuyến nó vào ba mẫu — start, stop, và mọi trường hợp khác (*) — in ra thông báo khác nhau cho mỗi cái. Kết thúc mỗi nhánh bằng ;; và đóng lại bằng esac.

③ Nhấn Esc, lưu bằng :wq, thêm quyền thực thi, rồi chạy nó với một tham số như ./service.sh start.

④ Đổi tham số thành ./service.sh stop hoặc ./service.sh restart và xác nhận mẫu khớp thay đổi.

⑤ Nếu bạn chưa chắc nên viết gì, hãy sao chép nội dung trong bảng đáp án rồi dán vào insert mode của vi.

Linux console
0 / 3 đã hoàn thành
Loading Linux Terminal...
QUIZ

Kiểm tra kiến thức

Hãy trả lời từng câu hỏi một.

Câu 1[ -f config.txt ] kiểm tra điều gì?

Câu 2Từ khóa nào thử một điều kiện khác khi điều kiện trước đó sai?

Câu 3Ký hiệu nào đánh dấu kết thúc hành động của mỗi mẫu trong case?