Xin chào các bạn, ở bài viết trước chúng ta đã được làm quen với các toán tử, các cú pháp so sánh và mảng trong bash. Cũng như các ngôn ngữ lập trình khác, Bash cũng có các cấu trúc điều khiển như rẽ nhánh, lặp...để có thể điều khiển code theo hướng mong muốn của chúng ta. Trong bài viết này, chúng ta hãy cùng nhau tìm hiểu về các cấu trúc điều khiển này nhé. Ngoài ra, trong bài viết này, chúng ta sẽ nói đến 1 kiểu dữ liệu mà nếu các bạn đã từng sử dụng hay  tương tác với python sẽ thấy được tác dụng tuyệt vời của nó, đó chính là "Dictionaries".

 

Các cấu trúc điều khiển:

  1. Rẽ Nhánh:
    • if 

      Cấu trúc:

      if [condition];
      then
         commands;
      fi​

      với [condition] ở đây là các cấu trúc so sánh đã được giới thiệu ở bài trước. "commands" là code thực thi mà ta muốn khi thoả mảng điều kiện [condition] ở trên.

      vd:
      if (( $a < $b )); 
      then
         echo "$a is smaller than $b"
      fi
      
      if [[ -e "file.txt" ]]; 
      then
         echo "file exists"
      fi
    • if - else, if - else if - else

      Cấu trúc:

      if [condition];
      then
           commands_01;
      else
          commands_02;                                     
      fi              
                                 
      if [condition];
      then
          commands;
      elif [condition];
      then
          commands;
      else
          commands;
      fi   
      vd:
      if [[ $a -lt 10 ]]; 
      then
        echo "a < 10"
      elif [[ $a -gt 20 ]]; 
      then
        echo "a > 20"
      else
        echo "a < 20 and a > 10"
      fi   
      Ngoài ra, ta còn có thể viết dưới dạng sau:
      # thực hiện nếu điều kiện condition là đúng (TRUE).
      [ condition ] && action 
      
      # thực hiện nếu điều kiện condition là sai (FALSE).
      [ condition ] || action 
    • case … esac
      Cấu trúc:
      case “$luachon” in
         giatrimau_1) Các câu lệnh ;;
         giatrimau_2) Các câu lệnh ;;
         giatrimau_n) Các câu lệnh ;;
         *) Câu lệnh cho TH còn lại ;; (Giống default trong C/C++)
      esac
      vd:
      case "$1" in
        1) echo 'Monday' ;;
        2) echo 'Tuesday' ;;
        3) echo 'Wednesday' ;;
        4) echo 'Thursday' ;;
        5) echo 'Friday' ;;
        6) echo 'Saturday' ;;
        7) echo 'Sunday' ;;
        *)
      
        echo "Don't match anything"
        exit 1
      
      ;;
      esac
      
      
      
      case "$1" in
        start | up)
          vagrant up
          ;;
      
        *)
          echo "Usage: $0 {start|stop|ssh}"
          ;;
      esac
  1. Vòng lặp:
    • for: hoạt động dựa trên danh sách của các mục. Nó lập đi lập lại một tập các câu lệnh cho mỗi mục có trong danh sách. Có thể sử duyệt mảng với điều kiện cho trước (khá giống với trong C/C++)
      • Vòng lặp cơ bản:
        for i in /etc/rc.*; do
          echo $i
        done
        
        
        for i in Mon Tue Wed Thurs Fri Sat Sun
        do
          echo $i
        done
      • Vòng lặp kiểu ngôn ngữ C (C-like)
        for ((i = 0 ; i < 100 ; i++)); 
        do
          echo $i
        done
        
        for (( i=0; $i < $elements; i++ ));
        do
          echo ${array[$i]}
        done
      • Vòng lặp khoảng số:
        for i in {1..5}; do
            echo "Welcome $i"
        done
        
        # lặp từ 5 -> 50 với mỗi step nhảy có giá trị 5 đơn vị.
        for i in {5..50..5}; do
            echo "Welcome $i"
        done
    • while: chủ yếu sử dụng vòng lặp này khi ta muốn thực thi một tập lệnh lặp đi lặp lại nhiều lần trong khi điều kiện vẫn còn đúng. (Ở phần điều kiện nếu là true thì vòng lặp while sẽ được thực thi)
      • Vòng while cơ bản:
        a=0
        while [ $a –le 5 ]
        do
          echo $a
          a=$(($a + 1))
        done
      • vòng while dùng để đọc file:
        < file.txt | while read line; 
        do
          echo $line
        done
    • until: ngược lại với while, vòng lặp này sẽ thực thi tập lệnh của nó khi giá trị điều kiện là sai. Nó sẽ chạy tới khi thỏa mãn điều kiện là đúng.
      a=0
      until [ ! $a –le 5 ]
      do
        echo $a
        a=$(($a + 1))
      done
    • select: vòng lặp cung cấp một danh sách menu từ một tập các phần tử được cho có đánh số ở đầu để lựa chọn. (Đây là vòng lặp có sẵn trong ksh được điều chỉnh vào bash. Nó không có sẵn trong bash
      #!/bin/bash
      
      select brand in Samsung Sony iphone symphony Walton
      do
      echo "You have chosen $brand"
      done
      
      
      select DRINK in tea cofee water juice appe all none
      do
         case $DRINK in
           tea|cofee|water|all)
              echo "Go to canteen"
              ;;
           juice|appe)
              echo "Available at home"
              ;;
           none)
              break
              ;;
           *) echo "ERROR: Invalid selection"
              ;;
        esac
      done
      

Các cách xử lý chuỗi đơn giản:

  1. Xoá chuỗi con trước chuỗi
    • #” : loại bỏ phần ngắn nhất ứng với $substring ở phía trước chuỗi $string.
    • ##” : loại bỏ phần dài nhất ứng với $substring ở phía trước chuỗi $string.
    • vd: Ta có chuỗi sau string="this is a name this is a substring test”
      substring1=${string#t*i}                                    
      substring2=${string##t*i}                                   
      Sau khi chạy lệnh trên ta sẽ được kết quả như sau:
      echo $substring1   # s is a name this is a substring test
      
      echo $substring2​   # ng test
      Mô tả cách hoạt động:
               string="this is a name this is a substring test”
                           |_|                                          |
                            #                                           |
                          |_______________________|
                                              ##
  2. Xoá chuỗi con sau chuỗi
    • %” : loại bỏ phần ngắn nhất ứng với $substring ở phía sau chuỗi $string. 
    • %%” : loại bỏ phần dài nhất ứng với $substring ở phía sau chuỗi $string.
    • vd: Ta có chuỗi sau string="this is a name this is a substring test”
      substring1=${string%n*t}                                    
      substring2=${string%%n*t}                                   
      Sau khi chạy lệnh trên ta sẽ được kết quả như sau:
      echo $substring1   # this is a name this is a substri
      echo $substring2​   # this is a
      Mô tả cách hoạt động:
               string="this is a name this is a substring test”
                                         |                                 |____|
                                         |                                    %
                                         |______________________|
                                                          %%
  3. Thay thế chuỗi
    Cấu Trúc: 
    # thay thế chuỗi con đầu tiên tìm thấy được
    ${string/[substring]/[replacement]}
    
    # thay thế tất cả chuỗi con tìm thấy được
    ${string//[substring]/[replacement]}​
    vd:
    string = “this is a name this is a substring test” 
    
    # thay thế chuỗi "this is a" đầu tiên tìm thấy được bằng "demo"
    # kết quả: demo name this is a substring test
    echo ${string/this is a/demo} 
    
    # thay thế tất cả chuỗi "this is a" tìm thấy được bằng "demo" 
    # kết quả: demo name demo substring test                      
    echo ${string//this is a/demo}                      ​
    Cấu trúc:
    # Nếu $substring ở phía đầu chuỗi $string thì thay thế $subtring thành $replacement.
    ${string/#substring/replacement}
    
    # Nếu $substring ở phía cuối chuỗi $string thì thay thế $subtring thành $replacement.
    ${string/%substring/replacement}​
    vd:
    string = “this is a name  substring test this is a” 
    
    echo ${string/#this is a/demo} # kq: demo name this is a substring test
    echo ${string/%this is a/demo} # kq: this is a name substring test demo​
  4. Độ dài chuỗi
    Cấu trúc:
    ${#string}​

    vd:

    string="this is a name this is a substring test"
    
    echo ${#string}     # kq: 39​
  5. Lấy ra xâu con của chuỗi bắt đầu tại vị trí i
    Cấu Trúc:
    ${string:position:length}​
    vd:
    string="this is a name this is a substring test"
    
    echo ${string:8:15}    # kq: a name this is​
  6. Viết thường ký tự đầu tiên của chuỗi
    STR="HELLO WORLD!"
    
    echo ${STR,}   # kq: hELLO WORLD!​
  7. Viết thường tất cả ký tự của chuỗi:
    STR="HELLO WORLD!"
    
    echo ${STR,,}  # kq: hello world!​
  8. Viết hoa ký tự đầu tiên của chuỗi:
    STR="hello world!"
    
    echo ${STR^}   # kq: Hello world! ​
  9. Viết hoa tất cả ký tự của chuỗi:
    STR="hello world!" 
    
    echo ${STR^^}  # kq: HELLO WORLD!​

Dictionaries:

  Dictionaries (Dictionary object) có thể được xem là 1 mảng kết hợp với cấu trúc "key" => "value" là một phần tử của mảng.

  1. Khai báo:
    declare -A sounds​
  2. Gán giá trị:
    sounds[dog]="bark"
    sounds[cow]="moo"
    sounds[bird]="tweet"
    sounds[wolf]="howl"​
  3. Lấy giá trị của key "dog"
    echo ${sounds[dog]}  # kq: bark​
  4. Lấy tất cả giá trị của "sounds"
    echo ${sounds[@]}   # kq: bark howl moo tweet​
  5. Lấy tất cả các key của "sounds"
    echo ${!sounds[@]}   # kq: dog wolf cow bird​
  6. Lấy số lượng phần tử có trong "sounds"
    echo ${#sounds[@]}    # kq: 4​
  7. Xoá 1 phần tử có "key" trong "sounds"
    unset sounds[dog]
    
    echo ${sounds[@]}   # kq: howl moo tweet​ ​
    echo ${!sounds[@]}   # kq: wolf cow bird​
  8. Lặp với Dictionaries
    # in ra tất cả giá trị của sounds
    for val in "${sounds[@]}"; do
      echo $val
    done
    
    # in ra tất cả key của sounds
    for key in "${!sounds[@]}"; do
      echo $key
    done​

 

Qua bài này, chúng ta đã có thể nắm được các cấu trúc điều khiển của bash, từ đó ta có thể viết được chương trình theo như mong muốn của chúng ta một cách dễ dàng. Hãy thật quen thuộc với các cấu trúc điều khiển này nhé, vì hầu như có thể nói, nếu ta nắm vững và sử dụng được các cấu trúc điều khiển này có thể giúp cho chương trình của chúng ta thực hiện hầu như tất cả mọi thứ mà chúng ta mong muốn đó. Ngoài ra, ta đã làm quen được với một kiểu dữ liệu mới là Dictionaries, với kiểu dữ liệu này, ta có thể tuỳ biến cách lưu trữ dữ liệu tạm của chúng ta 1 cách linh hoạt hơn, giúp ích cho chúng ta rất lớn trong việc xử lý vòng lặp và truy xuất gía trị mong muốn. 

Các bài viết liên quan: