Bash Script – Dàn cảnh và phức tạp hóa vấn đề với Conditional statements (If) và Boolean Logical Operations (And & Or)

Tiếp theo nội dung Bash Script – La liếm với bộ 3 Variable, Argument & User Input, như đã hứa hẹn, kỳ này tôi sẽ chiến với Conditional statements (tôi tạm dịch là mệnh đề điều kiện). Ngoài ra, một đối tượng khác có liên quan là Boolean Logical Operations (tạm dịch là các phép toán luận lý logic) cũng sẽ được đề cập.

Nội dung kỳ này hướng đến nhóm đối tượng gần như chưa từng đụng tới programming (lập trình). Nếu đã biết sơ bộ về programming với các ngôn ngữ khác (ví dụ Python), bạn có thể lướt nhanh qua các phần cơ bản và tập trung vào các điểm khác biệt (về Syntax – cú pháp và cách xử lý) đặc trưng của Bash script.

Lưu ý: Nếu chưa xem phần trước thì bạn chịu khó de lại để tìm hiểu các nội dung quan trọng sau (kỳ trước tôi nhai đi nhai lại đám này nhiều quá nên giờ ngán lắm rồi):

  • #!/bin/bash;
  • read command;
  • Tạo Bash script với text editor;
  • Cấp quyền thực thi cho file với chmod;
  • Chạy file Bash script.

#1 Dàn cảnh với Conditional statements trong Bash script

#1.1 Conditional statements – basic syntax

Conditional statements như bạn có thể đoán, là nhằm hỗ trợ việc lập kịch bản để thực hiện các hành động khác nhau tùy theo điều kiện thực tế. Và cũng như phần lớn các ngôn ngữ lập trình khác, dạng phổ biến nhất với Bash script cũng là đám if/elif/else.

Không nói dông dài nữa, tôi múc ngay cái ví dụ cho dễ hình dung với file test_if.sh có nội dung như sau:

#!/bin/bash

read -p "What is your math grade: " grade

if [ $grade -lt 5 ]

then

        echo "You died!"

fi

test if
test if

Kết quả chạy thử như sau:

test if result
test if result

Để dễ hình dung, bạn có thể phân tích dựa trên cú pháp đơn giản của thằng if như sau:

if [ <conditions> ]

then

        <actions>

fi

Như vậy, với ví dụ test_if.sh:

  • <conditions> sẽ tương ứng với “$grade -lt 5”;
  • < actions> sẽ tương ứng “echo “You died!””;

Dịch ra “tiếng người” phần xử lý của ví dụ nói trên: “Nếu điều kiện Grade (điểm) thấp hơn 5 là đúng, hiển thị dòng chữ ‘You died!’¸còn không đúng thì thôi

Lưu ý:

  • Đừng quên space (khoảng trắng) trước và sau cái <conditions>;
  • Bỏ cái ngoặc vuông “[ ]” script chạy cũng được nhưng nhìn chung bạn nên tập thói quen đặt <conditions> bên trong cho gọn đẹp và dễ mần việc về sau;
  • Nhớ ở đây có cái fi ở cuối cùng.

#1.2 Conditional statements – Operator

Trong ví dụ trên còn một thằng tôi chưa đề cập đó là -lt nằm trong <conditions>. lt (viết tắt của “less than”) là một trong các operator (tạm dịch là toán tử) phổ biến thường thấy trong các <conditions>. Ngoài thằng này, bạn còn có thể gặp đám sau:

Operator Mô tả
-n STRING STRING (chuỗi ký tự) có độ dài lớn hơn không
-z STRING STRING (chuỗi ký tự) có độ dài lớn bằng không
STRING1 != STRING2 STRING1 không bằng STRING2
STRING1 = STRING2 STRING1 bằng STRING2
INTEGER1 -eq INTEGER2 INTEGER1 bằng INTEGER2
INTEGER1 -ne INTEGER2 INTEGER1 không bằng INTEGER2
INTEGER1 -gt INTEGER2 INTEGER1 lớn hơn INTEGER2
INTEGER1 -lt INTEGER2 INTEGER1 nhỏ hơn INTEGER2
INTEGER1 -ge INTEGER2 INTEGER1 lớn hơn hoặc bằng INTEGER 2
INTEGER1 -le INTEGER2 INTEGER1 nhỏ hơn hoặc bằng INTEGER 2
-e FILE FILE tồn tại
-r FILE FILE tồn tại và có read permission (quyền đọc)
-s FILE FILE tồn tại và không rỗng
-w FILE FILE tồn tại và có write permission (quyền ghi)
-x FILE FILE tồn tại và có execute permission (quyền thực thi)

Lưu ý: Danh sách trên chỉ là mang tính chất giới thiệu, tùy nhu cầu thực tế mà bạn search thêm để biết cách xử lý. Ví dụ như muốn biết chi tiết hơn về việc kiểm tra file/directory có tồn tại thì bạn có thể đọc thằng này How to Check if a File or Directory Exists in Bash | Linuxize.

#1.3 Conditional statements – đẻ nhánh với Elif và Else

Với cái if syntax nói ở Mục 1.1, bạn chỉ có khả năng xử lý một tình huống khi <conditions> có kết quả là True. Nếu muốn xử lý tình huống nó ra kết quả False, bạn sẽ cần dùng đến nhánh Else theo cú pháp sau:

if [ <conditions> ]

then

        <actions>

else

        <other actions> 

fi

Tôi thử với file test_if_again.sh với nội dung như sau:

#!/bin/bash

read -p "What is your math grade: " grade

if [ $grade -lt 5 ]

then

        echo "You died!"

else

        echo "Congrats!"

fi

test if else
test if else

Kết quả chạy thử như sau:

test if else result
test if else result

Như vậy với test_if_again.sh, phần actions bên trong else sẽ được thực thi nếu <conditions> có kết quả là False (nghĩa là grade lớn hơn hoặc bằng 5).

Vậy nếu bạn thích rối rắm hơn và đẻ ra thêm tình huống xử lý khi “grade đúng bằng 5” thì sao? Lúc này, bạn có thể dùng thêm elif như syntax sau.

if [ <conditions> ]

then

        <actions>

efif [ <other conditions> ]

then

        <other actions>

else

        <other actions>

fi

Lưu ý: elif có syntax tương tự như nhánh if, bạn nhớ phần  space (khoảng trắng) trước và sau cái <conditions> then đi kèm.

Tôi tiếp tục demo với ví dụ test_if_again_x2.sh có nội dung như sau:

#!/bin/bash

read -p "What is your math grade: " grade

if [ $grade -lt 5 ]

then

        echo "You died!"

elif [ $grade -eq 5 ]

then

        echo "So close!"

else

        echo "Congrats!"

fi

test if elif else
test if elif else

Kết quả chạy thử như sau:

test if elif else result
test if elif else result

Đến đây coi như bạn đã nắm được “linh hồn” của đám Conditional statements. Nhưng nếu như thế vẫn chưa đáp ứng được dã tâm của bạn thì sao? Rất may mắn, bạn còn có Boolean Logical Operations hỗ trợ để kết hợp với Conditional statements phục vụ các ngữ cảnh phức tạp hơn.

#2 Phức tạp hóa vấn đề với Boolean Logical Operations trong Bash script

#2.1 Xử lý command lists với Boolean Logical Operations

Boolean Logical Operations nói chung và 2 thằng phổ biến nhất là AND (&&) OR (||) có khá nhiều đất diễn với Bash script. Bên cạnh việc hỗ trợ kết hợp với Conditional statements nói trên bạn còn có thể sử dụng đám này với command lists (chuỗi các command có thể kết nối với nhau).

Nếu bạn còn nhớ (quên cũng không sao, vì tôi sắp nhắc lại đây), command lists đơn giản gồm 2 command lsgrep với piping (|) như sau:

ls -la /usr/bin | grep zip

command lists example
command lists example

Lưu ý: Thằng piping tôi có bàn kỹ ở nội dung Giải ngố Kali Linux – Phần 5: Nâng cấp kỹ năng tìm kiếm trên Linux với grep command

Như bạn thấy output của thằng ls sẽ được hốt và dẫn sang grep (nhờ piping) để xác định cái nào trong đám output có dính líu đến zip.

Với Boolean Logical Operations, nguyên tắc xử lý cũng kiểu tương tự như vậy (nhưng có chọn lọc hơn). Tôi ví dụ minh họa ngay cho dễ hình dung như sau:

test_user=testkali

grep $test_user /etc/passwd && echo "$test_user found!"

Lưu ý:

  • Việc gán giá trị và tham chiếu đến Variable (test_user trong ví dụ trên) tôi đã giới thiệu kỹ trong nội dung Bash Script – La liếm với bộ 3 Variable, Argument & User Input. Nếu chưa rõ thì bạn chịu khó quay lại đó xem;
  • Nếu bạn không biết USERHOSTNAME tương ứng trên máy bạn là gì thì có thể nhìn vô chỗ đám chữ màu đỏ trên termial để đọc thông tin theo cú pháp USER@HOSTNAME (của tôi là testkali@kali) hoặc có thể kiểm tra lại kiểu như sau.
check user hostname
check user hostname

Dễ thấy (thú thật, lần đầu gặp thứ này tôi thấy khó thí mịa chứ dễ dàng gì), command lists sử dụng grep để thực hiện tìm kiếm username “testkali” có hiện diện trong file /etc/passwd hay không. Nếu kết quả của command grep trả về là True (tức là có tồn tại username “testkali” trong file /etc/passwd), command echo phía sau AND (&&) sẽ được thực thi (còn không có thì terminal sẽ đáp lại bằng thái độ im lặng đáng sợ).

command lists with AND
command lists with AND

Nếu không thích thái độ lạnh nhạt đó, bạn có thể cập nhật lại command lists như sau.

test_user=testkali

grep $test_user /etc/passwd && echo "$test_user found!" || echo "$test_user not found!"

command lists with OR
command lists with OR

Cũng lại dễ thấy, nếu kết quả của command grep trả về là False (ứng với tình huống không tồn tại username “testkali_fake” trong file /etc/passwd), command echo phía sau OR (||) sẽ được thực thi để báo cho bạn biết tình hình dò tìm username.

#2.2 Giao lưu phối hợp Conditional statements với Boolean Logical Operations

Quay trở lại câu chuyện với Conditional statements, tôi sẽ phức tạp hóa thêm vấn đề bằng cách kết hợp với Boolean Logical Operations như file test_if_again_x3.sh có nội dung sau:

#/bin/bash

if [ $USER == 'testkali' ] && [ $HOSTNAME == 'kali' ]

then

        echo "Yes, username is $USER AND hostname is $HOSTNAME!"

else

        echo "Who am I?"

fi   

Conditional statements with AND
Conditional statements with AND

Kết quả chạy thử:

Conditional statements with AND result
Conditional statements with AND result

Với ví dụ trên, chỉ khi cả $USER $HOSTNAME khớp với điều kiện kiểm tra, Conditional statements lúc này trả về giá trị True, bạn mới thấy dòng thông báo hiển thị $USER$HOSTNAME.

Tôi thử đổi Conditional statements liên quan đến $USER với giá trị trị vớ vẩn (testkali_fake) thì lúc này giá trị trả về sẽ là False nên bạn sẽ đọc được dòng echo của nhánh else bên dưới.

Conditional statements with AND (cont)
Conditional statements with AND (cont)

Kết quả chạy lại:

Conditional statements with AND (cont) result
Conditional statements with AND (cont) result

Nếu muốn chơi nhẹ nhàng tình cảm hơn, bạn có thể đổi điều kiện kiểm tra sang OR (||) thay vì AND (&&) như file test_if_again_x4.sh sau:

#/bin/bash

if [ $USER == 'testkali' ] || [ $HOSTNAME == 'not kali' ]

then

        echo "Yes, username is $USER OR hostname is $HOSTNAME!"

else

        echo "Seriously, you don’t even know your name?"

fi  

Conditional statements with OR
Conditional statements with OR

Kết quả chạy thử:

Conditional statements with OR result
Conditional statements with OR result

Lúc này, chỉ cần ăn hên dò trúng một trong 2 điều kiện $USER HOẶC $HOSTNAMEConditional statements trả về giá trị True để bạn tha hồ tung tóe.

Leave a Reply

Your email address will not be published. Required fields are marked *