So sanh bang trong linux script

Trong Bash có 1 số biến đặc biệt như sau:

Biến Đặc Biệt Ý Nghĩa
$0 Chứa tên file script hiện tại
$n ($1, $2,..$n) Với n có thể là 1, 2,… tương ứng với các tham số đưa vào khi gọi script.

VD: ./test.sh so01 so02 so03

Như VD trên thì có 3 tham số được đưa vào là so01, so02, so03 tương ứng với $1, $2, $3.

$# Tổng số tham số đã cung cấp cho script. Dựa theo VD trên thì kết quả khi dùng biến này sẽ ra 3
$* Chứa tất cả tham số được đưa vào script. Nếu script nhận 3 tham số thì giá trị sẽ là $1 $2 $3 khi sử dụng
[email protected] Chứa tất cả tham số nhưng phân biệt thành những tham số riêng lẽ không như $* được đưa vào script. Nếu script nhận 3 tham số thì giá trị sẽ là $1 $2 $3 khi sử dụng
$? Trạng thái thoát ra của lệnh trước được chạy (thường la 0 đại diện cho lệnh trước chạy thành công, khác 0 là failed) Max range [0 – 255]
$$ Số tiến trình của shell hiện tại. Đối với Shell script đây là số ProcessID mà chúng đang chạy
$! Số tiến trình của lệnh background trước

Sự khác nhau giữa $* và [email protected]: 

Về cơ bản thì $* và [email protected] giống nhau khi sử dụng với biến đơn không đặt trong dấu “”. Khi đặt vào trong dấu nháy kép “” thì:

  • $*: Các tham số đưa vào sẽ được nối thành một chuỗi và được phân cách nhau bởi dấu cách.
  • [email protected]: Các tham số đưa vào sẽ được phân biệt một cách riêng lẽ từng tham số một.

Ví dụ khác nhau giữa $* và [email protected]:

#!/bin/bash

echo -e "Using "$*":"
for str in "$*"
do
  echo $str

done


echo -e "Using "[email protected]":"
for str in "[email protected]"
do
  echo $str
done

Kết quả khi chạy script ./test.sh my name is Dang là:

# Khi sử dụng “$*” thì các tham số được xem là một chuỗi phân biệt bởi khoảng trắng
# Using "$*":

my name is Dang

# Khi sử dụng “[email protected]” thì các tham số được xem như các biến riêng lẽ được đặt trong một mảng
# Using "[email protected]":

my
name
is
Dang

Các toán tử cơ bản:

  • Về cơ bản thì shell linux sử dụng các toán tử cơ bản như các ngôn ngữ lập trình khác như C/C++, Java,… Tuy nhiên với toán tử nhân khi sử dụng nên dùng \* để phân biệt với lệnh bất kỳ * của linux
  • Sử dụng cú pháp: expr op1 op2 (để trong 2 dấu “ ` ” không phải nháy đơn đây là để thực thi lệnh shell expr)
echo `expr 2 + 3`  #sẽ hiển thị kết quả là 5

echo `expr 2 \* 3’ #kết quả là 2 * 3 = 6
  • Sử dụng cú pháp let “phép tính”
let “a=$a+3”

let ”c=$a*$b”

 Ngoài ra let có thể sử dụng các toán tử +=, -=, =+, =- khá tương tự như trong C/C++ và java

  • Sử dụng cú pháp: $((…)) 
Z=$(($a + $b))

Z=$(($a * $b))

Kiểm tra điều kiện (condition):

  • Có cấu trúc [ condition ] 
  • Trả về giá trị có kiểu boolean (true / false)

ví dụ:

if [4 -eq 2];
then
    echo True;
else
    echo False;
fi

# False

So sánh số học:

  • “-eq” => Bằng nhau (Equal)
  • “-ne” => Không bằng nhau (Not equal)
  • “-lt” => Nhỏ hơn (Less than)
  • “-gt” => Lớn hơn (Greater than)
  • “-le” => Nhỏ hơn hoặc bằng (Less or equal)
  • “-ge” => Lớn hơn hoặc bằng (Greater or equal)
  • “-o”  => OR
  • “-a”  => AND

Ví dụ:

var=10 
[ $var -eq 0 ] => FALSE

So sánh chuỗi:

  • [[ $str1 = $str2 ]] hoặc [[ $str1 == $str2 ]]
  • [[ $str1 != $str2 ]]
  • [[ $str1 > $str2 ]]
  • [[ $str1 < $str2 ]]
str1="HELLO" 
str2="Hello" 
[[ $str1 > $str2 ]] =>TRUE
  • [[ -z $str1 ]]: Trả về TRUE nếu $str1 là 1 chuỗi rỗng. FALSE nếu ngược lại
  • [[ -n $str1 ]]: Trả về TRUE nếu $str1 là 1 chuỗi khác rỗng. FALSE nếu ngược lại.

Kiểm tra tập tin:

  • [[ -f FILE ]] : Trả về TRUE nếu file_var là 1 tập tin.
  • [[ -x FILE ]]: Trả về TRUE nếu var là tập tin và có quyền thực thi (executable).
  • [[ -d FILE ]] : Trả về TRUE nếu var là 1 thư mục.
  • [[ -e FILE ]] : Trả về TRUE nếu var tồn tại.
  • [[ -w FILE ]] : Trả về TRUE nếu var là 1 tập tin và có quyền ghi (writable).
  • [[ -r FILE ]] : Trả về TRUE nếu var là 1 tập tin và có quyền đọc (readable).
  • [[ -h FILE ]] : Trả về TRUE nếu var là 1 liên kết mềm (symlink).
  • [[ -s FILE ]] : Trả về TRUE nếu file có dung lượng lớn hơn 0 bytes. 
  • [[ FILE1 -ef FILE2 ]] : Trả về TRUE nếu cùng là 1 file.

ví dụ:

fpath="/etc/passwd"

if [ -e $fpath ]; then
    echo File exists;
else
    echo Does not exist;
fi

mảng trong bash:

  • Cú pháp khai báo:
# =([giatri1] [giatri2] ... [giatrin])

list=(coffee water beer)
  • Lấy số lượng phần tử của mảng:
# ${#[@]}

elements = ${#list[@]}
  • Truy xuất phần tử trong mảng:
# ${[]
# sẽ cho giá trị đầu tiên trong mảng là coffee

${list[0]}
  • Tìm và thay thế phần tử trong mảng:
# ${[@]/pt_find/pt_replace}
# lệnh này sẽ thay thế phần tử có giá trị coffee thành milk

${list[@]/coffee/milk}
  • In tất cả phần tử, phân cách bởi space
# ${[@]}

${Fruits[@]}
  • Độ dài chuỗi của phần tử đầu tiên
# ${#}

${#Fruits}
  • Độ dài chuỗi của phần tử n
# ${#[vị trí n]}

${#Fruits[3]}
  • Lấy mảng con từ vị trí n với m phần tử.
# ${[@]::}

# lấy từ vị trí 3, 2 phần tử
${Fruits[@]:3:2}
  • Thêm phần tử (Push).
#  =("${[@]}" "[phần tử cần thêm]")

Fruits=("${Fruits[@]}" "Watermelon")

# +=('[phần tử cần thêm]')

Fruits+=('Watermelon')
  • Xoá phần tử:
# Remove by regex match
# =( ${[@]/[regex match]}/ )

Fruits=( ${Fruits[@]/Ap*/} )

# Xoá phần tử ở vị trí n
# unset [vị trí n]

unset Fruits[2]
  • Tạo bản sao
# =("${[@]")

list=("1" "2" "3")
list2=("${list[@]}")

echo ${list2[@]}
# 1 2 3
  • Nối mảng:
list=("1" "2" "3")
list2=("4" "5" "6")

# =("${[@]}" "${[@]}")
list3=("${list[@]}" "${list2[@]}")

echo ${list3[@]}
# 1 2 3 4 5 6
  • Tạo mảng từ file
# =(`cat "đường dẫn file"`)

lines=(`cat "logfile"`)

Qua bài viết trên, chúng ta đã nắm được các toán tử cơ bản trong bash, cách thực hiện các phép tính toán, các phép so sánh số học và chuỗi, kiểu dữ liệu mảng (array). Sau bài viết, các bạn hãy thực hành thêm về các toán tử cơ bản trên để nắm chắc về chúng nhé vì chúng sẽ hổ trợ rất nhiều cho chúng ta trong việc học tập lập trình ngôn ngữ Bash sau này đó. Bài viết sau, mình sẽ cùng các bạn tìm hiểu về các cấu trúc điều khiển và các toán tử xử lý chuỗi trong ngôn ngữ Bash.