Bash shell là công cụ dòng lệnh mạnh mẽ và linh hoạt bậc nhất trong hệ điều hành Linux, đồng thời cũng là một trong những lý do hàng đầu khiến các lập trình viên, quản trị hệ thống và người dùng kỹ thuật lựa chọn Linux để làm việc.
Với Bash, bạn có thể tương tác trực tiếp qua terminal, viết các Bash script để tự động hóa quy trình, tối ưu hiệu suất và giảm thiểu thao tác lặp đi lặp lại. Mặc dù với người mới, Bash scripting có thể trông khá phức tạp, nhưng trên thực tế, việc làm quen và bắt đầu viết script lại đơn giản hơn bạn nghĩ rất nhiều – đặc biệt khi bạn có hướng dẫn rõ ràng và ví dụ thực tế để làm theo.
Bash Script là gì?
Bash script là một tập tin văn bản chứa tập hợp các lệnh được viết dành riêng cho Bash shell – trình thông dịch dòng lệnh phổ biến trên hệ điều hành Unix-based như Linux và macOS. Bash script thường được sử dụng để tự động hóa các tác vụ lặp đi lặp lại, thực thi nhiều lệnh liên tiếp, hoặc xây dựng những chương trình đơn giản giúp tăng hiệu suất công việc.
Nếu bạn đã quen thao tác với dòng lệnh trên Linux, thì việc viết Bash script không quá xa lạ – bởi mọi lệnh trong Bash script đều có thể thực thi trực tiếp trên terminal. Trong bài hướng dẫn này, chúng tôi sẽ giới thiệu tới bạn các ví dụ thực tế, giúp bạn hình dung rõ cách vận hành của Bash script và cách khai thác hiệu quả các tính năng mạnh mẽ mà Bash mang lại.
Từ người mới đến chuyên gia chỉ cách nhau vài dòng lệnh! Bạn hoàn toàn có thể bắt đầu bằng việc sao chép các đoạn script mẫu vào hệ thống, thử chạy, tinh chỉnh, và luyện tập thường xuyên. Chúng tôi sẽ đồng hành cùng bạn trên từng bước để chinh phục thế giới Bash scripting. Hãy cùng bắt đầu hành trình tự động hóa với Bash!
Trong hướng dẫn Bash scripting này, bạn sẽ học:
- Cách viết script “Hello World” đầu tiên
- Cách truyền tham số vào Bash script
- Cách sử dụng biến toàn cục và cục bộ trong Bash
- Cách đọc input từ người dùng
- Cách sử dụng và đọc mảng trong Bash
- Cách so sánh số nguyên và chuỗi
- Cách kiểm tra kiểu file trong Bash
- Cách sử dụng vòng lặp for, while và until
- Cách định nghĩa và sử dụng hàm trong Bash
- Cách sử dụng câu lệnh if
- Cách sử dụng câu lệnh case
- Cách xử lý dấu nháy và ký tự đặc biệt trong Bash
- Cách thực hiện phép tính số học trong Bash
- Cách sử dụng tính năng redirection (chuyển hướng) trong Bash
Yêu cầu phần mềm và quy ước dòng lệnh linux
Danh mục | Yêu cầu, quy ước hoặc phiên bản phần mềm sử dụng |
---|---|
Hệ thống | Hệ điều hành Linux |
Phần mềm | Bash shell (được cài mặc định) |
Khác | Quyền truy cập root hoặc sử dụng sudo |
Quy Ước:
Script Hello World trong Bash – Hướng dẫn Bash Scripting
1. Trước tiên, bạn cần xác định vị trí của trình thông dịch Bash trên hệ thống. Hãy nhập lệnh sau vào dòng lệnh terminal:
$ which bash /bin/bash
Lệnh này sẽ cho bạn biết rằng Bash shell được lưu tại đường dẫn /bin/bash
. Thông tin này sẽ rất quan trọng trong bước tiếp theo.
2. Tiếp theo, hãy mở trình soạn thảo văn bản yêu thích của bạn và tạo một file có tên là hello_world.sh
. Ở đây, chúng ta sẽ sử dụng nano cho đơn giản:
$ nano hello_world.sh
3. Sao chép và dán đoạn mã dưới đây vào file vừa tạo, sau đó lưu lại:
#!/bin/bash # declare STRING variable STRING="Hello World" # print variable on a screen echo $STRING
SHEBANG là gì?
Tất cả các Bash script trong hướng dẫn này đều bắt đầu bằng shebang
#!
, đây không phải là một comment. Dòng đầu tiên khai báo interpreter (trình thông dịch) sẽ được dùng – trong trường hợp này là/bin/bash
.
4. Tiếp theo, điều hướng tới thư mục chứa file hello_world.sh
và cấp quyền thực thi cho script:
$ chmod +x hello_world.sh
5. Giờ bạn đã sẵn sàng để chạy script đầu tiên:
$ ./hello_world.sh
Output:
Hello World
Bạn vừa tạo, lưu và thực thi thành công một Bash script đơn giản!
Script Backup đơn giản với Bash
Khi bạn viết một Bash script, thực chất bạn chỉ đang gói gọn các lệnh mà bạn có thể chạy trực tiếp trên dòng lệnh. Ví dụ hoàn hảo:
#!/bin/bash tar -czf myhome_directory.tar.gz /home/linuxconfig
Lệnh này sẽ tạo file nén .tar.gz
chứa toàn bộ thư mục home của user linuxconfig
. Bạn hoàn toàn có thể chạy trực tiếp lệnh tar
này trên dòng lệnh.
Vậy lợi ích của việc viết script là gì?
Script giúp bạn không cần ghi nhớ lệnh dài dòng, có thể tái sử dụng dễ dàng, và thuận tiện để mở rộng logic về sau.
Biến Trong Bash Script
Ví dụ sau khai báo một biến $STRING
đơn giản và in ra với lệnh echo
:
#!/bin/bash STRING="HELLO WORLD!!!" echo $STRING
Kết quả khi chạy script:
$ ./hello_world.sh HELLO WORLD!!!
Giờ ta quay lại ví dụ backup phía trên và dùng biến để đặt tên file backup, có đính kèm timestamp (dấu thời gian) bằng lệnh date
:
#!/bin/bash OF=myhome_directory_$(date +%Y%m%d).tar.gz tar -czf $OF /home/linuxconfig
Chạy script:
$ ./backup.sh $ ls myhome_directory_$(date +20220209).tar.gz
File kết quả cho ta biết backup được thực hiện vào ngày 9/2/2022.
Biến Toàn Cục vs. Cục Bộ Trong Bash
Trong Bash scripting, biến toàn cục (global variable) là biến có thể được sử dụng ở bất kỳ đâu trong toàn bộ script. Ngược lại, biến cục bộ (local variable) chỉ có thể được sử dụng bên trong hàm (function) nơi nó được khai báo.
Hãy xem ví dụ dưới đây, trong đó chúng ta khai báo cả biến toàn cục và biến cục bộ. Một số chú thích đã được thêm vào trong script để giúp bạn dễ hiểu hơn.
#!/bin/bash # Define bash global variable # This variable is global and can be used anywhere in this bash script VAR="global variable" function bash { # Define bash local variable # This variable is local to bash function only local VAR="local variable" echo $VAR } echo $VAR bash # Note the bash global variable did not change # "local" is bash reserved word echo $VAR
Kết quả khi thực thi script này:
$ ./variables.sh global variable local variable global variable
Truyền tham số vào Bash Script
Khi bạn chạy một Bash script, bạn có thể truyền tham số (argument) vào script ngay từ dòng lệnh. Xem ví dụ dưới đây:
#!/bin/bash # use predefined variables to access passed arguments #echo arguments to the shell echo $1 $2 $3 ' -> echo $1 $2 $3' # We can also store arguments from bash command line in special array args=("$@") #echo arguments to the shell echo ${args[0]} ${args[1]} ${args[2]} ' -> args=("$@"); echo ${args[0]} ${args[1]} ${args[2]}' #use $@ to print out all arguments at once echo $@ ' -> echo $@' # use $# variable to print out # number of arguments passed to the bash script echo Number of arguments passed: $# ' -> echo Number of arguments passed: $#'
Chạy thử script với 3 tham số:
$ ./arguments.sh Bash Scripting Tutorial
Kết quả:
Bash Scripting Tutorial -> echo $1 $2 $3 Bash Scripting Tutorial -> args=("$@"); echo ${args[0]} ${args[1]} ${args[2]} Bash Scripting Tutorial -> echo $@ Number of arguments passed: 3 -> echo Number of arguments passed: $#
Thực thi lệnh shell trong Bash
Cách tốt nhất để thực thi một lệnh shell riêng biệt bên trong Bash script là tạo một subshell bằng cú pháp $( )
. Xem ví dụ dưới đây – chúng ta sử dụng echo
để in kết quả của lệnh uname -o
:
#!/bin/bash # use a subshell $() to execute shell command echo $(uname -o) # executing bash command without subshell echo uname -o
Lưu ý rằng ở dòng cuối cùng, chúng ta không đặt lệnh uname
trong subshell, vì vậy Bash chỉ in ra văn bản thô “uname -o” thay vì kết quả của lệnh.
Ví dụ thực tế:
$ uname -o GNU/LINUX $ ./subshell.sh GNU/LINUX uname -o
Đọc dữ liệu người dùng nhập vào
Chúng ta có thể sử dụng lệnh read
để nhận input từ người dùng. Cách này cho phép người dùng tương tác với Bash script và điều khiển luồng xử lý. Ví dụ dưới đây:
#!/bin/bash echo -e "Hi, please type the word: \c " read word echo "The word you entered is: $word" echo -e "Can you please enter two words? " read word1 word2 echo "Here is your input: \"$word1\" \"$word2\"" echo -e "How do you feel about bash scripting? " # read command now stores a reply into the default build-in variable $REPLY read echo "You said $REPLY, I'm glad to hear that! " echo -e "What are your favorite colours ? " # -a makes read command to read into an array read -a colours echo "My favorite colours are also ${colours[0]}, ${colours[1]} and ${colours[2]}:-)"
Script Bash này sẽ lần lượt đặt câu hỏi cho người dùng và ghi nhận phản hồi vào biến và mảng, sau đó lặp lại những gì người dùng đã nhập:
$ ./read.sh Hi, please type the word: Linuxconfig.org The word you entered is: Linuxconfig.org Can you please enter two words? Debian Linux Here is your input: "Debian" "Linux" How do you feel about bash scripting? good You said good, I'm glad to hear that! What are your favorite colours ? blue green black My favorite colours are also blue, green and black:-)
Lệnh trap
trong Bash
Lệnh trap
trong Bash cho phép script bắt được các tín hiệu hệ thống (signals), ví dụ như khi người dùng nhấn tổ hợp Ctrl + C, và thực hiện một hàm xử lý tương ứng.
Ví dụ bên dưới cho thấy cách trap
hoạt động khi phát hiện tín hiệu INT
(tín hiệu ngắt – interrupt):
#!/bin/bash # bash trap command trap bashtrap INT # bash clear screen command clear; # bash trap function is executed when CTRL-C is pressed: # bash prints message => Executing bash trap subrutine ! bashtrap() { echo "CTRL+C Detected !...executing bash trap !" } # for loop from 1/10 to 10/10 for a in `seq 1 10`; do echo "$a/10 to Exit." sleep 1; done echo "Exit Bash Trap Example!!!"
Kết quả khi thực thi và cố tình nhấn Ctrl + C:
$ ./trap.sh 1/10 to Exit. 2/10 to Exit. ^CCTRL+C Detected !...executing bash trap ! 3/10 to Exit. 4/10 to Exit. 5/10 to Exit. 6/10 to Exit. 7/10 to Exit. ^CCTRL+C Detected !...executing bash trap ! 8/10 to Exit. 9/10 to Exit. 10/10 to Exit. Exit Bash Trap Example!!!
Bạn có thể thấy rằng mặc dù người dùng đã nhấn Ctrl+C, script không bị dừng lại mà vẫn tiếp tục thực thi nhờ xử lý qua trap
.
Mảng trong Bash – Hướng dẫn Bash scripting
Bash hỗ trợ lưu trữ nhiều giá trị trong mảng (arrays). Dưới đây là hai ví dụ minh họa cách sử dụng mảng:
1. Khai báo mảng đơn giản trong Bash
Ví dụ sau khai báo một mảng với 4 phần tử:
#!/bin/bash #Declare array with 4 elements ARRAY=( 'Debian Linux' 'Redhat Linux' Ubuntu Linux ) # get number of elements in the array ELEMENTS=${#ARRAY[@]} # echo each element in array # for loop for (( i=0;i<$ELEMENTS;i++)); do echo ${ARRAY[${i}]} done
Kết quả khi chạy:
$ ./arrays.sh Debian Linux Redhat Linux Ubuntu Linux
2. Đọc nội dung file vào mảng trong Bash
Thay vì khai báo trực tiếp từng phần tử, chúng ta có thể đọc từ nội dung file để điền dữ liệu vào mảng:
#!/bin/bash # Declare array declare -a ARRAY # Link filedescriptor 10 with stdin exec 10<&0 # stdin replaced with a file supplied as a first argument exec < $1 let count=0 while read LINE; do ARRAY[$count]=$LINE ((count++)) done echo Number of elements: ${#ARRAY[@]} # echo array's content echo ${ARRAY[@]} # restore stdin from filedescriptor 10 # and close filedescriptor 10 exec 0<&10 10<&-
Khi thực thi script, truyền vào một file văn bản chứa nội dung từng dòng. Mỗi dòng sẽ trở thành một phần tử của mảng.
$ cat bash.txt Bash Scripting Tutorial Guide $ ./bash-script.sh bash.txt Number of elements: 4 Bash Scripting Tutorial Guide
Câu lệnh if / else / fi trong Bash
Dưới đây là một ví dụ đơn giản về câu lệnh if
kiểm tra xem một thư mục có tồn tại hay không. Tùy vào kết quả kiểm tra, script sẽ thực hiện một trong hai hành động. Lưu ý quan trọng: phải có dấu cách giữa dấu [
và ]
. Nếu không có khoảng trắng, câu lệnh sẽ không hoạt động!
#!/bin/bash directory="./BashScripting" # bash check if directory exists if [ -d $directory ]; then echo "Directory exists" else echo "Directory does not exist" fi
Kết quả khi chạy script:
$ ./bash_if_else.sh Directory does not exist $ mkdir BashScripting $ ./bash_if_else.sh Directory exists
if / else lồng nhau
Bạn hoàn toàn có thể đặt một câu lệnh if
bên trong một if
khác. Cách viết này gọi là nested if (câu lệnh lồng nhau). Tuy nhiên, script có thể trở nên phức tạp nếu lồng quá sâu nhiều tầng.
Ví dụ sau sẽ yêu cầu người dùng chọn từ một danh sách, và xử lý lựa chọn bằng if/else lồng nhau:
#!/bin/bash # Declare variable choice and assign value 4 choice=4 # Print to stdout echo "1. Bash" echo "2. Scripting" echo "3. Tutorial" echo -n "Please choose a word [1,2 or 3]? " # Loop while the variable choice is equal 4 # bash while loop while [ $choice -eq 4 ]; do # read user input read choice # bash nested if/else if [ $choice -eq 1 ] ; then echo "You have chosen word: Bash" else if [ $choice -eq 2 ] ; then echo "You have chosen word: Scripting" else if [ $choice -eq 3 ] ; then echo "You have chosen word: Tutorial" else echo "Please make a choice between 1-3 !" echo "1. Bash" echo "2. Scripting" echo "3. Tutorial" echo -n "Please choose a word [1,2 or 3]? " choice=4 fi fi fi done
Kết quả khi chạy script:
$ ./nested_if_else.sh 1. Bash 2. Scripting 3. Tutorial Please choose a word [1,2 or 3]? 5 Please make a choice between 1-3 ! 1. Bash 2. Scripting 3. Tutorial Please choose a word [1,2 or 3]? 2 You have chosen word: Scripting
So sánh trong Bash
Bash hỗ trợ so sánh các giá trị (số hoặc chuỗi) để kiểm tra chúng có bằng nhau hay không, hoặc lớn hơn/nhỏ hơn…
Các toán tử so sánh số học:
Toán tử | Ý nghĩa |
---|---|
-lt |
nhỏ hơn < |
-gt |
lớn hơn > |
-le |
nhỏ hơn hoặc bằng <= |
-ge |
lớn hơn hoặc bằng >= |
-eq |
bằng == |
-ne |
không bằng != |
Ví dụ 1 – So sánh bằng nhau
#!/bin/bash # declare integers NUM1=2 NUM2=2 if [ $NUM1 -eq $NUM2 ]; then echo "Both values are equal" else echo "Values are NOT equal" fi
Kết quả:
$ ./statement.sh Both values are equal
Ví dụ 2 – So sánh không bằng
#!/bin/bash # declare integers NUM1=2 NUM2=1 if [ $NUM1 -eq $NUM2 ]; then echo "Both Values are equal" else echo "Values are NOT equal" fi
Kết quả:
$ ./statement.sh Values are NOT equal
Ví dụ 3 – Sử dụng elif
để xác định số lớn hơn
#!/bin/bash # declare integers NUM1=2 NUM2=1 if [ $NUM1 -eq $NUM2 ]; then echo "Both values are equal" elif [ $NUM1 -gt $NUM2 ]; then echo "NUM1 is greater than NUM2" else echo "NUM2 is greater than NUM1" fi
Kết quả:
$ ./statement.sh NUM1 is greater than NUM2
So sánh chuỗi trong Bash
Toán tử | Ý nghĩa |
---|---|
= |
bằng nhau (equal) |
!= |
khác nhau (not equal) |
< |
nhỏ hơn (less than) |
> |
lớn hơn (greater than) |
-n s1 |
chuỗi s1 không rỗng |
-z s1 |
chuỗi s1 rỗng |
Bước 1: Thử so sánh hai chuỗi để xem chúng có bằng nhau không:
#!/bin/bash #Declare string S1 S1="Bash" #Declare string S2 S2="Scripting" if [ $S1 = $S2 ]; then echo "Both Strings are equal" else echo "Strings are NOT equal" fi
Kết quả:
$ ./statement.sh Strings are NOT equal
Bước 2: Thử lại với hai chuỗi giống hệt nhau:
#!/bin/bash #Declare string S1 S1="Bash" #Declare string S2 S2="Bash" if [ $S1 = $S2 ]; then echo "Both Strings are equal" else echo "Strings are NOT equal" fi
Kết quả:
$ ./statement.sh Both Strings are equal
Kiểm tra file trong Bash
Trong Bash, bạn có thể kiểm tra nhiều thuộc tính khác nhau của file hoặc thư mục. Dưới đây là bảng tổng hợp:
Tùy chọn | Mô tả |
---|---|
-b filename |
File đặc biệt dạng block |
-c filename |
File đặc biệt dạng ký tự |
-d directoryname |
Kiểm tra thư mục có tồn tại |
-e filename |
Kiểm tra file có tồn tại |
-f filename |
Kiểm tra file thông thường (không phải thư mục) |
-G filename |
File tồn tại và thuộc group ID của user |
-g filename |
File có bit set-group-ID |
-k filename |
File có sticky bit |
-L filename |
Là symbolic link |
-O filename |
File tồn tại và thuộc quyền sở hữu của user |
-r filename |
File có thể đọc được |
-S filename |
File dạng socket |
-s filename |
File có kích thước lớn hơn 0 |
-u filename |
File có set-user-ID bit |
-w filename |
File có thể ghi được |
-x filename |
File có thể thực thi được |
Kiểm tra file có tồn tại hay không:
#!/bin/bash file="./file" if [ -e $file ]; then echo "File exists" else echo "File does not exist" fi
Kết quả:
$ ./filetesting.sh File does not exist $ touch file $ ./filetesting.sh File exists
Tương tự, chúng ta có thể sử dụng vòng lặp while
để kiểm tra xem một file chưa tồn tại. Script dưới đây sẽ tạm dừng (sleep) cho đến khi file được tạo ra (tức là tồn tại).
Lưu ý dấu !
trong Bash – đây là toán tử phủ định, dùng để phủ định điều kiện -e
(kiểm tra file tồn tại).
#!/bin/bash while [ ! -e myfile ]; do # Sleep until file does exists/is created sleep 1 done
Loops
Bash hỗ trợ nhiều loại vòng lặp như for
, while
, và until
. Dưới đây là một số ví dụ:
Bash for loop
Script sau sẽ liệt kê tất cả các file/thư mục trong thư mục /var/
:
#!/bin/bash # bash for loop for f in $( ls /var/ ); do echo $f done
Bạn cũng có thể chạy vòng lặp for ngay trong dòng lệnh:
$ for f in $( ls /var/ ); do echo $f; done
Kết quả:
$ ./for_loop.sh backups cache crash lib local lock log mail metrics opt run snap spool tmp
Bash while loop
Vòng lặp while này sẽ tiếp tục cho đến khi biến COUNT
nhỏ hơn hoặc bằng 0:
#!/bin/bash COUNT=6 # bash while loop while [ $COUNT -gt 0 ]; do echo Value of count is: $COUNT let COUNT=COUNT-1 done
Kết quả:
$ ./while_loop.sh Value of count is: 6 Value of count is: 5 Value of count is: 4 Value of count is: 3 Value of count is: 2 Value of count is: 1
Bash until loop
until
loop tương tự như while
, nhưng ngược điều kiện:
#!/bin/bash COUNT=0 # bash until loop until [ $COUNT -gt 5 ]; do echo Value of count is: $COUNT let COUNT=COUNT+1 done
Kết quả:
$ ./until_loop.sh Value of count is: 0 Value of count is: 1 Value of count is: 2 Value of count is: 3 Value of count is: 4 Value of count is: 5
Điều khiển vòng lặp bằng input người dùng
Ví dụ này sử dụng vòng lặp while
để tìm và thay thế khoảng trắng trong tên file bằng _
:
#!/bin/bash # This bash script will locate and replace spaces # in the filenames DIR="." # Controlling a loop with bash read command by redirecting STDOUT as # a STDIN to while loop # find will not truncate filenames containing spaces find $DIR -type f | while read file; do # using POSIX class [:space:] to find space in the filename if [[ "$file" = *[[:space:]]* ]]; then # substitute space with "_" character and consequently rename the file mv "$file" `echo $file | tr ' ' '_'` fi; # end of while loop done
Hàm trong Bash
Ví dụ dưới đây cho thấy cách khai báo và gọi hàm trong Bash:
!/bin/bash # BASH FUNCTIONS CAN BE DECLARED IN ANY ORDER function function_B { echo Function B. } function function_A { echo $1 } function function_D { echo Function D. } function function_C { echo $1 } # FUNCTION CALLS # Pass parameter to function A function_A "Function A." function_B # Pass parameter to function C function_C "Function C." function_D
Kết quả khi chạy:
$ ./functions.sh Function A. Function B. Function C. Function D.
Bash Select – Tạo menu chọn trong Bash
Lệnh select
trong Bash cho phép bạn tạo menu lựa chọn để người dùng dễ dàng tương tác.
#!/bin/bash PS3='Choose one word: ' # bash select select word in "linux" "bash" "scripting" "tutorial" do echo "The word you have selected is: $word" # Break, otherwise endless loop break done exit 0
Kết quả:
$ ./select.sh 1) linux 2) bash 3) scripting 4) tutorial Choose one word: 2 The word you have selected is: bash
Câu lệnh điều kiện case
trong Bash
Lệnh case
giúp xử lý nhiều điều kiện một cách ngắn gọn và dễ đọc hơn so với if/else
khi có nhiều lựa chọn:
#!/bin/bash echo "What is your preferred programming / scripting language" echo "1) bash" echo "2) perl" echo "3) phyton" echo "4) c++" echo "5) I do not know !" read case; #simple case bash structure # note in this case $case is variable and does not have to # be named case this is just an example case $case in 1) echo "You selected bash";; 2) echo "You selected perl";; 3) echo "You selected phyton";; 4) echo "You selected c++";; 5) exit esac
Kết quả:
$ ./case.sh What is your preferred programming / scripting language 1) bash 2) perl 3) phyton 4) c++ 5) I do not know ! 3 You selected phyton
Dấu nháy và trích dẫn trong Bash
Dấu nháy và trích dẫn là một phần quan trọng trong Bash và lập trình Bash script. Dưới đây là những kiến thức cơ bản bạn cần nắm về cách sử dụng dấu nháy trong Bash.
Thoát ký tự đặc biệt
Trước khi tìm hiểu về dấu nháy và trích dẫn trong Bash, bạn cần hiểu khái niệm escape ký tự đặc biệt (meta characters). Việc escape sẽ vô hiệu hóa ý nghĩa đặc biệt của các ký tự đó, giúp Bash đọc chúng theo nghĩa chữ (literal) thay vì xử lý như lệnh hay biến.
Để escape ký tự đặc biệt, chúng ta sử dụng dấu gạch chéo ngược \
. Ví dụ:
#!/bin/bash #Declare bash string variable BASH_VAR="Bash Script" # echo variable BASH_VAR echo $BASH_VAR #when meta character such us "$" is escaped with "\" it will be read literally echo \$BASH_VAR # backslash has also special meaning and it can be suppressed with yet another "\" echo "\\"
Kết quả:
$ ./escape_meta.sh Bash Script $BASH_VAR \
Dấu nháy đơn ' '
Khi đặt nội dung trong dấu nháy đơn, mọi ký tự đặc biệt bên trong sẽ bị vô hiệu hóa, kể cả dấu $
.
#!/bin/bash # Declare bash string variable BASH_VAR="Bash Script" # echo variable BASH_VAR echo $BASH_VAR # meta characters special meaning in bash is suppressed when using single quotes echo '$BASH_VAR "$BASH_VAR"'
Kết quả:
$ ./single_quotes.sh Bash Script $BASH_VAR "$BASH_VAR"
Dấu nháy kép " "
Trong Bash, dấu nháy kép (" "
) sẽ vô hiệu hóa ý nghĩa đặc biệt của hầu hết các ký tự đặc biệt, ngoại trừ:
$
(biến),\
(escape),- và
`
(lệnh nội dòng – command substitution).
Tất cả các ký tự đặc biệt khác sẽ được Bash hiểu theo nghĩa chữ (literal).
Ngoài ra, bạn có thể đặt dấu nháy đơn ('
) bên trong dấu nháy kép mà không gặp lỗi. Nếu bạn muốn sử dụng dấu nháy kép bên trong một cặp dấu nháy kép, thì cần escape bằng ký tự \
.
Ví dụ:
#!/bin/bash #Declare bash string variable BASH_VAR="Bash Script" # echo variable BASH_VAR echo $BASH_VAR # meta characters and its special meaning in bash is # suppressed when using double quotes except "$", "\" and "`" echo "It's $BASH_VAR and \"$BASH_VAR\" using backticks: `date`"
Kết quả:
$ ./double_quotes.sh Bash Script It's Bash Script and "Bash Script" using backticks: Thu 10 Feb 2022 10:24:15 PM EST
Trích dẫn kiểu ANSI-C ($'...'
)
Ngoài các kiểu trích dẫn thông thường, Bash còn hỗ trợ một kiểu trích dẫn khác gọi là trích dẫn theo chuẩn ANSI-C.
Với kiểu trích dẫn này, các ký tự được escape bằng dấu \
sẽ mang ý nghĩa đặc biệt theo quy chuẩn của ANSI-C.
Dưới đây là một số ký tự escape phổ biến:
\a
– chuông cảnh báo (alert/bell)\b
– backspace\e
– ký tự escape\f
– form feed\n
– xuống dòng (newline)\r
– quay về đầu dòng (carriage return)\t
– tab ngang\v
– tab dọc\\
– ký tự backslash\'
– dấu nháy đơn\nnn
– ký tự có giá trị bát phân (octal)\xnn
– ký tự có giá trị thập lục phân (hex)
Cú pháp trích dẫn kiểu ANSI-C trong Bash là: $' '
#!/bin/bash # as a example we have used \n as a new line, \x40 is hex value for @ # and \56 is octal value for . echo $'web: www.linuxconfig.org\nemail: web\x40linuxconfig\56org'
Kết quả:
$ ./bash_ansi-c.sh web: www.linuxconfig.org email: web@linuxconfig.org
Toán học trong Bash
Bash có thể được sử dụng để thực hiện các phép tính toán. Hãy cùng xem một vài ví dụ để hiểu cách thực hiện điều đó trong thực tế.
Cộng hai số – ví dụ đơn giản:
#!/bin/bash let RESULT1=$1+$2 echo $1+$2=$RESULT1 ' -> # let RESULT1=$1+$2' declare -i RESULT2 RESULT2=$1+$2 echo $1+$2=$RESULT2 ' -> # declare -i RESULT2; RESULT2=$1+$2' echo $1+$2=$(($1 + $2)) ' -> # $(($1 + $2))'
Kết quả:
$ ./bash_addition_calc.sh 88 12 88+12=100 -> # let RESULT1=$1+$2 88+12=100 -> # declare -i RESULT2; RESULT2=$1+$2 88+12=100 -> # $(($1 + $2))
Phép toán số học cơ bản trong Bash
Hãy cùng tìm hiểu cách thực hiện một số phép toán cơ bản trong Bash như cộng, trừ, nhân, chia, v.v.
#!/bin/bash echo '### let ###' # bash addition let ADDITION=3+5 echo "3 + 5 =" $ADDITION # bash subtraction let SUBTRACTION=7-8 echo "7 - 8 =" $SUBTRACTION # bash multiplication let MULTIPLICATION=5*8 echo "5 * 8 =" $MULTIPLICATION # bash division let DIVISION=4/2 echo "4 / 2 =" $DIVISION # bash modulus let MODULUS=9%4 echo "9 % 4 =" $MODULUS # bash power of two let POWEROFTWO=2**2 echo "2 ^ 2 =" $POWEROFTWO echo '### Bash Arithmetic Expansion ###' # There are two formats for arithmetic expansion: $[ expression ] # and $(( expression #)) its your choice which you use echo 4 + 5 = $((4 + 5)) echo 7 - 7 = $[ 7 - 7 ] echo 4 x 6 = $((3 * 2)) echo 6 / 3 = $((6 / 3)) echo 8 % 7 = $((8 % 7)) echo 2 ^ 8 = $[ 2 ** 8 ] echo '### Declare ###' echo -e "Please enter two numbers \c" # read user input read num1 num2 declare -i result result=$num1+$num2 echo "Result is:$result " # bash convert binary number 10001 result=2#10001 echo $result # bash convert octal number 16 result=8#16 echo $result # bash convert hex number 0xE6A result=16#E6A echo $result
Kết quả:
$ ./arithmetic_operations.sh ### let ### 3 + 5 = 8 7 - 8 = -1 5 * 8 = 40 4 / 2 = 2 9 % 4 = 1 2 ^ 2 = 4 ### Bash Arithmetic Expansion ### 4 + 5 = 9 7 - 7 = 0 4 x 6 = 6 6 / 3 = 2 8 % 7 = 1 2 ^ 8 = 256 ### Declare ### Please enter two numbers 23 45 Result is:68 17 14 3690
Làm tròn số thực trong Bash
#!/bin/bash # get floating point number floating_point_number=3.3446 echo $floating_point_number # round floating point number with bash for bash_rounded_number in $(printf %.0f $floating_point_number); do echo "Rounded number with bash:" $bash_rounded_number done
Kết quả:
$ ./round.sh 3.3446 Rounded number with bash: 3
Tính toán số thực với bc
#!/bin/bash # Simple linux bash calculator echo "Enter input:" read userinput echo "Result with 2 digits after decimal point:" echo "scale=2; ${userinput}" | bc echo "Result with 10 digits after decimal point:" echo "scale=10; ${userinput}" | bc echo "Result as rounded integer:" echo $userinput | bc
Kết quả:
$ ./simple_bash_calc.sh Enter input: 10/3.4 Result with 2 digits after decimal point: 2.94 Result with 10 digits after decimal point: 2.9411764705 Result as rounded integer: 2
Chuyển hướng trong Bash
Trong các ví dụ sau đây, chúng ta sẽ tìm hiểu cách chuyển hướng (redirect) lỗi chuẩn (standard error – STDERR) và đầu ra chuẩn (standard output – STDOUT) trong Bash.
Chuyển hướng STDOUT sang STDERR
#!/bin/bash echo "Redirect this STDOUT to STDERR" 1>&2
Để chứng minh rằng STDOUT đã được chuyển hướng sang STDERR, chúng ta có thể chuyển hướng đầu ra của script vào một file như sau:
$ ./redirecting.sh Redirect this STDOUT to STDERR $ ./redirecting.sh > STDOUT.txt $ cat STDOUT.txt $ $ ./redirecting.sh 2> STDERR.txt $ cat STDERR.txt Redirect this STDOUT to STDERR
Chuyển hướng STDERR sang STDOUT
#!/bin/bash cat $1 2>&1
Để chứng minh rằng STDERR đã được chuyển hướng sang STDOUT, chúng ta có thể chuyển hướng đầu ra của script vào một file như sau:
$ ./redirecting.sh /etc/shadow cat: /etc/shadow: Permission denied $ ./redirecting.sh /etc/shadow > STDOUT.txt $ cat STDOUT.txt cat: /etc/shadow: Permission denied $ ./redirecting.sh /etc/shadow 2> STDERR.txt cat: /etc/shadow: Permission denied $ cat STDERR.txt $
Chuyển hướng STDOUT ra màn hình
Cách đơn giản nhất để chuyển hướng đầu ra chuẩn (stdout) là chỉ cần sử dụng bất kỳ lệnh nào, vì mặc định stdout sẽ tự động hiển thị ra màn hình.
Trước tiên, hãy tạo một file tên là file1
:
$ touch file1 $ ls file1 file1
Như bạn có thể thấy từ ví dụ trên, khi thực thi lệnh ls
, nó tạo ra STDOUT và theo mặc định, được hiển thị lên màn hình.
Chuyển hướng stdout sang file
Để thay đổi hành vi mặc định của STDOUT, chúng ta có thể sử dụng ký hiệu >
để chuyển hướng đầu ra này vào một file như sau:
$ ls file1 > STDOUT $ cat STDOUT file1
Chuyển STDERR sang file
Mặc định, STDERR (lỗi chuẩn) sẽ được hiển thị trên màn hình:
$ ls file1 STDOUT $ ls file2 ls: cannot access file2: No such file or directory
Trong ví dụ dưới đây, chúng ta sẽ chuyển hướng STDERR vào một file, còn STDOUT vẫn hiển thị trên màn hình như bình thường.
Lưu ý rằng: kết quả của file1
(STDOUT) được in ra màn hình, trong khi lỗi liên quan đến file2
(STDERR) được ghi vào file có tên là STDERR
:
$ ls file1 STDOUT $ ls file1 file2 2> STDERR file1 $ cat STDERR ls: cannot access file2: No such file or directory
Chuyển hướng STDOUT sang STDERR
Bạn cũng có thể chuyển hướng cả STDOUT (đầu ra chuẩn) và STDERR (lỗi chuẩn) vào cùng một file. Trong ví dụ dưới đây, chúng ta sẽ chuyển STDOUT về cùng bộ mô tả (descriptor) với STDERR, do đó cả hai sẽ được ghi vào file có tên là STDERR_STDOUT
:
$ ls file1 STDERR STDOUT $ ls file1 file2 2> STDERR_STDOUT 1>&2 $ cat STDERR_STDOUT ls: cannot access file2: No such file or directory file1
File STDERR_STDOUT
giờ đây đã chứa cả STDOUT và STDERR.
Chuyển hướng STDERR sang STDOUT
Bạn cũng có thể đảo ngược ví dụ trên, bằng cách chuyển STDERR về cùng descriptor với STDOUT:
$ ls file1 STDERR STDOUT $ ls file1 file2 > STDERR_STDOUT 2>&1 $ cat STDERR_STDOUT ls: cannot access file2: No such file or directory file1
Chuyển cả STDOUT và STDERR vào một file
Hai ví dụ trước đều cho thấy cách chuyển hướng cả STDOUT và STDERR vào cùng một file. Dưới đây là một cách viết khác để đạt cùng mục tiêu đó:
$ ls file1 STDERR STDOUT $ ls file1 file2 &> STDERR_STDOUT $ cat STDERR_STDOUT ls: cannot access file2: No such file or directory file1
Hoặc:
ls file1 file2 >& STDERR_STDOUT $ cat STDERR_STDOUT ls: cannot access file2: No such file or directory file1
Tổng kết
Trong hướng dẫn Bash scripting này, bạn đã được làm quen với những nền tảng quan trọng nhất để bắt đầu hành trình làm chủ dòng lệnh – từ vòng lặp, toán học, so sánh giá trị, xử lý lỗi, đến trích dẫn và chuyển hướng dữ liệu. Mỗi phần đều mở ra một góc nhìn mới về cách mà Bash hoạt động và cách bạn có thể tận dụng nó để tự động hóa quy trình, tối ưu hiệu suất làm việc, hoặc đơn giản là trở thành người dùng Linux thành thạo hơn.
Đây chỉ là bước khởi đầu. Khi bạn tiếp tục luyện tập, thử nghiệm và sáng tạo với các ví dụ trong bài viết – biến chúng thành công cụ phục vụ cho công việc thực tế của bạn – thì kỹ năng Bash scripting của bạn sẽ tiến bộ một cách tự nhiên và vững chắc.
Hãy tiếp tục viết script, tự động hóa những việc lặp đi lặp lại, và biến terminal thành môi trường làm việc mạnh mẽ nhất của bạn!