Shell AIO
Vì bash là trình thông dịch shell mặc định của Linux, có thể nói bash là cơ sở của lập trình shell.
Bài viết này tập trung giới thiệu cú pháp của bash, không giới thiệu bất kỳ lệnh Linux nào.
███████╗██╗ ██╗███████╗██╗ ██╗
██╔════╝██║ ██║██╔════╝██║ ██║
███████╗███████║█████╗ ██║ ██║
╚════██║██╔══██║██╔══╝ ██║ ██║
███████║██║ ██║███████╗███████╗███████╗
Giới thiệu
Shell là gì
- Shell là một chương trình được viết bằng ngôn ngữ C, nó là cầu nối giữa người dùng và Linux.
- Shell vừa là ngôn ngữ lệnh, vừa là ngôn ngữ lập trình.
- Shell chỉ một loại ứng dụng, ứng dụng này cung cấp một giao diện, người dùng sử dụng giao diện này để truy cập vào dịch vụ của nhân Linux.
Sh là loại Shell Unix đầu tiên của Ken Thompson, Windows Explorer là một loại Shell giao diện đồ họa điển hình.
Shell script là gì
Shell script (shell script) là một loại chương trình kịch bản được viết cho shell, thường có phần mở rộng tệp là .sh
.
Trong ngành công nghiệp, shell thường chỉ đề cập đến shell script, nhưng shell và shell script là hai khái niệm khác nhau.
Môi trường Shell
Lập trình Shell giống như lập trình Java, PHP, chỉ cần một trình soạn thảo văn bản để viết mã và một trình thông dịch mã lệnh để thực thi.
Có nhiều loại trình thông dịch Shell, phổ biến nhất là:
- sh - Bourne Shell. sh là shell mặc định của Unix.
- bash - Bourne Again Shell. bash là shell mặc định của Linux.
- fish - Shell dòng lệnh thông minh và thân thiện với người dùng.
- xiki - Làm cho giao diện điều khiển shell thân thiện hơn và mạnh mẽ hơn.
- zsh - Shell và ngôn ngữ kịch bản mạnh mẽ.
Chỉ định trình thông dịch kịch bản
Trong shell script, #!
cho biết chương trình được chỉ định sau đường dẫn là trình thông dịch shell để thực thi tệp script. #!
được gọi là shebang (còn được gọi là Hashbang).
Vì vậy, bạn có thể thấy các chú thích như sau trong shell:
- Chỉ định trình thông dịch sh
- Chỉ định trình thông dịch bash
Chú ý
Cách chỉ định trình thông dịch trên là phổ biến, nhưng đôi khi bạn cũng có thể thấy cách sau:
Lợi ích của cách này là hệ thống sẽ tự động tìm chương trình bạn chỉ định (trong trường hợp này là
bash
) trong biến môi trườngPATH
. So với cách đầu tiên, bạn nên sử dụng cách này nếu có thể, vì đường dẫn của chương trình là không xác định. Cách viết này cũng có một lợi ích khác, biến môi trườngPATH
của hệ điều hành có thể được cấu hình để trỏ đến phiên bản khác của chương trình. Ví dụ, sau khi cài đặt phiên bản mới củabash
, chúng tôi có thể thêm đường dẫn của nó vàoPATH
để “ẩn” phiên bản cũ. Nếu bạn sử dụng#!/bin/bash
, hệ thống sẽ chọn phiên bản cũ củabash
để thực thi tệp script, trong khi nếu bạn sử dụng#!/usr/bin/env bash
, nó sẽ sử dụng phiên bản mới hơn.
Chế độ
Shell có hai chế độ là tương tác và không tương tác.
Chế độ tương tác
Đơn giản mà nói, bạn có thể hiểu chế độ tương tác của shell là thực thi dòng lệnh.
Khi bạn thấy điều sau đây, điều đó cho thấy shell đang ở chế độ tương tác:
Sau đó, bạn có thể nhập một chuỗi lệnh Linux như ls
, grep
, cd
, mkdir
, rm
, v.v.
Chế độ không tương tác
Đơn giản mà nói, bạn có thể hiểu chế độ không tương tác của shell là thực thi shell script.
Trong chế độ không tương tác, shell đọc lệnh từ tệp tin hoặc ống và thực thi.
Khi trình thông dịch shell thực thi xong lệnh cuối cùng trong tệp tin, quá trình shell kết thúc và trở lại quá trình cha.
Bạn có thể sử dụng các lệnh sau để chạy shell ở chế độ không tương tác:
Trong ví dụ trên, script.sh
là một tệp văn bản thông thường chứa các lệnh mà trình thông dịch shell có thể nhận dạng và thực thi, sh
và bash
là các chương trình trình thông dịch shell. Bạn có thể sử dụng bất kỳ trình soạn thảo nào bạn thích để tạo script.sh
(vim, nano, Sublime Text, Atom, v.v.).
Ngoài ra, bạn cũng có thể sử dụng lệnh chmod
để cấp quyền thực thi cho tệp tin và chạy tệp tin script trực tiếp:
Cách tiếp cận này yêu cầu dòng đầu tiên của tệp tin script chỉ định chương trình chạy script đó, ví dụ:
💻 『Mã nguồn minh họa』
Trong ví dụ trên, chúng ta sử dụng lệnh echo
hữu ích để in ra chuỗi lên màn hình.
Cú pháp cơ bản
Trình thông dịch
Mặc dù đã đề cập đến #!
hai lần trước đó, nhưng để đảm bảo rằng điều quan trọng được nói ba lần, tôi sẽ nhấn mạnh một lần nữa:
Trong shell script, #!
cho biết chương trình được chỉ định sau đường dẫn là trình thông dịch shell để thực thi tệp script. #!
được gọi là shebang (còn được gọi là Hashbang).
#!
xác định rằng tệp script có thể được thực thi như một tệp tin thực thi độc lập, mà không cần nhập sh
, bash
, python
, php
, v.v. vào trước dòng lệnh đó.
Chú thích
Chú thích giúp giải thích mã của bạn có tác dụng gì và tại sao lại viết như vậy.
Trong cú pháp shell, chú thích là một loại câu lệnh đặc biệt, được bỏ qua bởi trình thông dịch shell.
- Chú thích một dòng - Bắt đầu bằng
#
và kết thúc ở cuối dòng. - Chú thích nhiều dòng - Bắt đầu bằng
:<<EOF
và kết thúc ởEOF
.
💻 『Mã nguồn minh họa』
echo
echo được sử dụng để in ra chuỗi.
In ra chuỗi thông thường:
In ra chuỗi chứa biến:
In ra chuỗi chứa biến:
In ra chuỗi chứa ký tự xuống dòng:
In ra chuỗi mà không xuống dòng:
Định hướng đầu ra vào tệp tin:
In ra kết quả thực thi:
💻 『Mã nguồn minh họa』
printf
printf được sử dụng để định dạng chuỗi đầu ra.
Mặc định, printf không tự động thêm ký tự xuống dòng như echo, nếu cần xuống dòng, bạn có thể thêm \n
thủ công.
💻 『Mã nguồn minh họa』
Các ký tự thoát của printf
Chuỗi | Mô tả |
---|---|
\a | Ký tự cảnh báo, thường là ký tự BEL ASCII |
\b | Ký tự backspace |
\c | Không hiển thị ký tự xuống dòng cuối cùng trong kết quả đầu ra (chỉ có hiệu lực trong chuỗi tham số của định dạng %b) và bỏ qua bất kỳ ký tự, tham số tiếp theo và ký tự trong chuỗi định dạng |
\f | Ký tự xuống trang (formfeed) |
\n | Ký tự xuống dòng |
\r | Ký tự carriage return |
\t | Ký tự tab ngang |
\v | Ký tự tab dọc |
\\ | Ký tự backslash chính nó |
\ddd | Ký tự đại diện cho giá trị bát phân từ 1 đến 3 chữ số. Chỉ có hiệu lực trong chuỗi định dạng |
\0ddd | Ký tự đại diện cho giá trị bát phân từ 1 đến 3 chữ số |
Biến
Giống như nhiều ngôn ngữ lập trình khác, bạn có thể tạo biến trong bash.
Trong bash, không có kiểu dữ liệu cụ thể. Biến trong bash có thể lưu trữ một số, một ký tự, một chuỗi và nhiều hơn nữa. Bạn không cần phải khai báo biến trước, gán giá trị cho biến sẽ tự động tạo biến.
Quy tắc đặt tên biến
- Tên biến chỉ có thể sử dụng chữ cái, số và dấu gạch dưới, ký tự đầu tiên không thể là số.
- Không có khoảng trắng, có thể sử dụng dấu gạch dưới (_) thay thế.
- Không sử dụng các ký tự đặc biệt.
- Không sử dụng các từ khóa của bash (có thể sử dụng lệnh
help
để xem từ khóa được bảo lưu).
Khai báo biến
Cú pháp truy cập biến là: ${var}
và $var
.
Dấu ngoặc nhọn bên ngoài tên biến là tùy chọn, có thể có hoặc không, nhưng nên sử dụng dấu ngoặc nhọn để giúp trình thông dịch nhận biết ranh giới của biến, vì vậy khuyến nghị sử dụng dấu ngoặc nhọn.
Biến chỉ đọc
Bạn có thể sử dụng lệnh readonly
để định nghĩa biến là biến chỉ đọc, giá trị của biến chỉ đọc không thể thay đổi.
Xóa biến
Bạn có thể sử dụng lệnh unset
để xóa biến. Sau khi xóa biến, bạn không thể sử dụng lại biến đó. Lệnh unset
không thể xóa biến chỉ đọc.
Loại biến
- Biến cục bộ - Biến cục bộ chỉ có hiệu lực trong một script cụ thể. Chúng không thể được truy cập bởi các chương trình hoặc script khác.
- Biến môi trường - Biến môi trường là biến mà tất cả các chương trình hoặc script trong phiên làm việc hiện tại đều có thể nhìn thấy. Để tạo biến môi trường, bạn sử dụng từ khóa
export
, các script shell cũng có thể định nghĩa biến môi trường.
Các biến môi trường phổ biến:
Biến | Mô tả |
---|---|
$HOME | Thư mục người dùng hiện tại |
$PATH | Danh sách thư mục được phân tách bằng dấu chấm phẩy, shell sẽ tìm kiếm các lệnh trong các thư mục này |
$PWD | Thư mục làm việc hiện tại |
$RANDOM | Số ngẫu nhiên từ 0 đến 32767 |
$UID | ID người dùng hiện tại (kiểu số) |
$PS1 | Chuỗi dấu nhắc chính |
$PS2 | Chuỗi dấu nhắc phụ |
Bảng này cung cấp một danh sách biến môi trường Bash phổ biến hơn.
💻 『Mã nguồn minh họa』
Chuỗi
Dấu nháy đơn và dấu nháy kép
Trong shell, chuỗi có thể được bao bọc bằng dấu nháy đơn ''
hoặc dấu nháy kép ""
, hoặc không cần dùng dấu nháy.
- Đặc điểm của dấu nháy đơn:
- Dấu nháy đơn không nhận diện biến.
- Dấu nháy đơn không thể chứa dấu nháy đơn đơn lẻ (dù có sử dụng ký tự escape), nhưng có thể xuất hiện theo cặp, được sử dụng để nối chuỗi.
- Đặc điểm của dấu nháy kép:
- Dấu nháy kép nhận diện biến.
- Dấu nháy kép có thể chứa ký tự escape.
Tóm lại, khuyến nghị sử dụng dấu nháy kép.
Nối chuỗi
Lấy độ dài chuỗi
Cắt chuỗi con
Cắt 2 ký tự từ vị trí thứ 3 của chuỗi
Tìm kiếm chuỗi con
Tìm vị trí bắt đầu của chuỗi con ll
trong chuỗi hello
.
💻 『Mã nguồn ví dụ』
Mảng
Bash chỉ hỗ trợ mảng một chiều.
Chỉ số mảng bắt đầu từ 0 và có thể là số nguyên hoặc biểu thức số học, giá trị phải lớn hơn hoặc bằng 0.
Tạo mảng
Truy cập phần tử mảng
- Truy cập một phần tử mảng:
- Truy cập tất cả các phần tử mảng:
Có một sự khác biệt quan trọng (và tinh vi) giữa hai dòng trên:
Để in từng phần tử của mảng trên một dòng riêng biệt, chúng ta sử dụng lệnh printf
:
Tại sao dark
và blue
mỗi cái chiếm một dòng? Hãy thử đặt trong dấu ngoặc kép:
Bây giờ tất cả các phần tử đều được in trên cùng một dòng - điều này không phải là những gì chúng ta muốn! Hãy thử ${colors[@]}
Trong dấu ngoặc kép, ${colors[@]}
mở rộng thành từng phần tử của mảng là một đối số riêng biệt; khoảng trắng trong các phần tử mảng được giữ nguyên.
- Truy cập một phần của mảng:
Trong ví dụ trên, ${array[@]}
mở rộng thành toàn bộ mảng, :0:2
lấy các phần tử của mảng từ vị trí 0 và có độ dài là 2.
Truy cập độ dài của mảng
Thêm phần tử vào mảng
Thêm phần tử vào mảng cũng rất đơn giản:
Trong ví dụ trên, ${colors[@]}
mở rộng thành toàn bộ mảng và được gán vào câu lệnh gán phức hợp, sau đó, phép gán cho mảng colors
ghi đè lên giá trị ban đầu của nó.
Xóa phần tử khỏi mảng
Sử dụng lệnh unset
để xóa một phần tử khỏi mảng:
💻 『Mã nguồn ví dụ』
Toán tử
Toán tử số học
Bảng dưới đây liệt kê các toán tử số học phổ biến, giả sử biến x có giá trị là 10 và biến y có giá trị là 20:
Toán tử | Mô tả | Ví dụ |
---|---|---|
+ | Phép cộng | expr $x + $y kết quả là 30. |
- | Phép trừ | expr $x - $y kết quả là -10. |
* | Phép nhân | expr $x * $y kết quả là 200. |
/ | Phép chia | expr $y / $x kết quả là 2. |
% | Lấy phần dư | expr $y % $x kết quả là 0. |
= | Gán giá trị | x=$y sẽ gán giá trị của biến y cho biến x. |
== | So sánh bằng. Sử dụng để so sánh hai số, nếu giống nhau thì trả về true. | [ $x == $y ] trả về false. |
!= | So sánh khác nhau. Sử dụng để so sánh hai số, nếu khác nhau thì trả về true. | [ $x != $y ] trả về true. |
Lưu ý: Biểu thức điều kiện phải được đặt trong dấu ngoặc vuông và phải có khoảng trắng, ví dụ: [$x==$y]
là sai, phải viết thành [ $x == $y ]
.
💻 『Mã nguồn ví dụ』
Toán tử quan hệ
Toán tử quan hệ chỉ hỗ trợ số, không hỗ trợ chuỗi trừ khi giá trị chuỗi là số.
Bảng dưới đây liệt kê các toán tử quan hệ phổ biến, giả sử biến x có giá trị là 10 và biến y có giá trị là 20:
Toán tử | Mô tả | Ví dụ |
---|---|---|
-eq | Kiểm tra hai số có bằng nhau không, nếu bằng nhau thì trả về true. | [ $a -eq $b ] trả về false. |
-ne | Kiểm tra hai số có khác nhau không, nếu khác nhau thì trả về true. | [ $a -ne $b ] trả về true. |
-gt | Kiểm tra số bên trái có lớn hơn số bên phải không, nếu có thì trả về true. | [ $a -gt $b ] trả về false. |
-lt | Kiểm tra số bên trái có nhỏ hơn số bên phải không, nếu có thì trả về true. | [ $a -lt $b ] trả về true. |
-ge | Kiểm tra số bên trái có lớn hơn hoặc bằng số bên phải không, nếu có thì trả về true. | [ $a -ge $b ] trả về false. |
-le | Kiểm tra số bên trái có nhỏ hơn hoặc bằng số bên phải không, nếu có thì trả về true. | [ $a -le $b ] trả về true. |
💻 『Mã nguồn ví dụ』
Toán tử boolean
Bảng dưới đây liệt kê các toán tử boolean phổ biến, giả sử biến x có giá trị là 10 và biến y có giá trị là 20:
Toán tử | Mô tả | Ví dụ |
---|---|---|
! | Phủ định, nếu biểu thức là true thì trả về false, ngược lại trả về true. | [ ! false ] trả về true. |
-o | Logic OR, nếu một trong hai biểu thức là true thì trả về true. | [ $a -lt 20 -o $b -gt 100 ] trả về true. |
-a | Logic AND, cả hai biểu thức đều là true thì trả về true. | [ $a -lt 20 -a $b -gt 100 ] trả về false. |
💻 『Mã nguồn ví dụ』
Toán tử logic
Dưới đây là các toán tử logic trong Shell, giả sử biến x có giá trị là 10 và biến y có giá trị là 20:
Toán tử | Mô tả | Ví dụ |
---|---|---|
&& | Logic AND [[ {x} -lt 100 && {y} -gt 100 ]] | |
` | ` |
💻 『Mã nguồn ví dụ』
Toán tử chuỗi
Bảng dưới đây liệt kê các toán tử chuỗi phổ biến, giả sử biến a có giá trị là “abc” và biến b có giá trị là “efg”:
Toán tử | Mô tả | Ví dụ |
---|---|---|
= | Kiểm tra hai chuỗi có bằng nhau không, nếu bằng nhau thì trả về true. | [ $a = $b ] trả về false. |
!= | Kiểm tra hai chuỗi có khác nhau không, nếu khác nhau thì trả về true. | [ $a != $b ] trả về true. |
-z | Kiểm tra độ dài của chuỗi có bằng 0 không, nếu bằng 0 thì trả về true. | [ -z $a ] trả về false. |
-n | Kiểm tra độ dài của chuỗi có khác 0 không, nếu khác 0 thì trả về true. | [ -n $a ] trả về true. |
str | Kiểm tra chuỗi có rỗng không, nếu không rỗng thì trả về true. | [ $a ] trả về true. |
💻 『Mã nguồn ví dụ』
Toán tử kiểm tra tệp tin
Toán tử kiểm tra tệp tin được sử dụng để kiểm tra các thuộc tính của tệp tin Unix.
Mô tả kiểm tra thuộc tính như sau:
Toán tử | Mô tả | Ví dụ |
---|---|---|
-b file | Kiểm tra xem tệp tin có phải là tệp thiết bị khối hay không, nếu đúng thì trả về true. | [ -b $file ] trả về false. |
-c file | Kiểm tra xem tệp tin có phải là tệp thiết bị ký tự hay không, nếu đúng thì trả về true. | [ -c $file ] trả về false. |
-d file | Kiểm tra xem tệp tin có phải là thư mục hay không, nếu đúng thì trả về true. | [ -d $file ] trả về false. |
-f file | Kiểm tra xem tệp tin có phải là tệp thông thường (không phải thư mục hoặc thiết bị) hay không, nếu đúng thì trả về true. | [ -f $file ] trả về true. |
-g file | Kiểm tra xem tệp tin có được đặt cờ SGID hay không, nếu đúng thì trả về true. | [ -g $file ] trả về false. |
-k file | Kiểm tra xem tệp tin có được đặt cờ Sticky Bit hay không, nếu đúng thì trả về true. | [ -k $file ] trả về false. |
-p file | Kiểm tra xem tệp tin có phải là ống thông tin (named pipe) hay |
Câu điều khiển
Câu điều kiện
Tương tự như các ngôn ngữ lập trình khác, câu điều kiện trong Bash cho phép chúng ta quyết định xem một hành động có được thực hiện hay không. Kết quả phụ thuộc vào một biểu thức được đặt trong cặp dấu [[ ]]
.
Biểu thức được bao bọc trong [[ ]]
(trong sh
là [ ]
) được gọi là lệnh kiểm tra hoặc nguyên tố. Những biểu thức này giúp chúng ta kiểm tra kết quả của một điều kiện. Bạn có thể tìm thấy câu trả lời về sự khác biệt giữa dấu ngoặc vuông đơn và kép trong bash tại đây.
Có hai loại biểu thức điều kiện: if
và case
.
if
(1) Câu lệnh if
Câu lệnh if
trong Bash hoạt động tương tự như các ngôn ngữ khác. Nếu biểu thức trong dấu ngoặc vuông là đúng, thì mã giữa then
và fi
sẽ được thực thi. fi
đánh dấu kết thúc của khối mã điều kiện.
(2) Câu lệnh if else
Tương tự, chúng ta cũng có thể sử dụng câu lệnh if..else
, ví dụ:
(3) Câu lệnh if elif else
Đôi khi, câu lệnh if..else
không đáp ứng được yêu cầu của chúng ta. Đừng quên câu lệnh if..elif..else
, nó cũng rất tiện lợi để sử dụng.
💻 『Mã nguồn ví dụ』
case
Nếu bạn cần xử lý nhiều trường hợp khác nhau và thực hiện các hành động khác nhau cho từng trường hợp, thì sử dụng câu lệnh case
sẽ hữu ích hơn việc lồng if
. Sử dụng case
để giải quyết các điều kiện phức tạp, có dạng như sau:
💻 『Mã nguồn ví dụ』
Mỗi trường hợp tương ứng với một biểu thức mẫu. Dấu |
được sử dụng để phân tách các mẫu khác nhau, dấu )
được sử dụng để kết thúc một chuỗi mẫu. Câu lệnh tương ứng với mẫu đầu tiên khớp sẽ được thực thi. Dấu *
đại diện cho bất kỳ mẫu nào không khớp với các mẫu được đưa ra trước đó. Các khối lệnh phải được phân tách bằng ;;
.
Vòng lặp
Vòng lặp không lạ lẫm. Tương tự như các ngôn ngữ lập trình khác, vòng lặp trong bash là một khối mã được lặp đi lặp lại cho đến khi điều kiện điều khiển trở thành sai.
Bash có bốn loại vòng lặp: for
, while
, until
và select
.
Vòng lặp for
for
rất giống với nó trong C. Nó có dạng như sau:
Trong mỗi lần lặp, arg
sẽ được gán giá trị từ elem1
đến elemN
. Các giá trị này cũng có thể là các ký tự đại diện hoặc mở rộng dấu ngoặc nhọn.
Tất nhiên, chúng ta cũng có thể viết vòng lặp for
trên một dòng, nhưng điều này yêu cầu phải có một dấu chấm phẩy trước do
, như sau:
Ngoài ra, nếu bạn cảm thấy cú pháp for..in..do
hơi lạ lẫm, bạn cũng có thể sử dụng for
giống như trong C, ví dụ:
Khi chúng ta muốn thực hiện cùng một hành động trên tất cả các tệp trong một thư mục, for
rất hữu ích. Ví dụ, nếu chúng ta muốn di chuyển tất cả các tệp có đuôi .bash
vào thư mục script
và cấp quyền thực thi cho chúng, script của chúng ta có thể được viết như sau:
💻 『Mã nguồn ví dụ』
Vòng lặp while
Vòng lặp while
kiểm tra một điều kiện, và chỉ thực thi một khối lệnh khi điều kiện đó là đúng. Điều kiện được kiểm tra trong while
tương tự như trong câu lệnh if..then
với nguyên tố được sử dụng. Vì vậy, một vòng lặp while
có dạng như sau:
Tương tự như vòng lặp for
, nếu chúng ta viết do
và điều kiện kiểm tra trên cùng một dòng, chúng ta phải thêm một dấu chấm phẩy trước do
.
💻 『Mã nguồn ví dụ』
Vòng lặp until
Vòng lặp until
tương tự như vòng lặp while
, nhưng ngược lại. Nó kiểm tra một điều kiện và chỉ thực thi một khối lệnh khi điều kiện đó là sai:
💻 『Mã nguồn ví dụ』
Vòng lặp select
Vòng lặp select
giúp chúng ta tạo một menu cho người dùng. Cú pháp của nó gần giống với vòng lặp for
:
select
sẽ in ra các giá trị elem1..elemN
và số thứ tự của chúng trên màn hình, sau đó yêu cầu người dùng nhập vào. Thông thường, bạn sẽ thấy $?
(biến PS3
). Kết quả lựa chọn của người dùng sẽ được lưu vào biến answer
. Nếu answer
là một số trong khoảng từ 1
đến N
, thì câu lệnh sẽ được thực thi và sau đó sẽ tiếp tục vòng lặp - trừ khi bạn không muốn điều đó, bạn có thể sử dụng câu lệnh break
.
💻 『Mã nguồn ví dụ』
Ví dụ này đầu tiên hỏi người dùng muốn sử dụng trình quản lý gói nào. Sau đó, nó hỏi người dùng muốn cài đặt gói nào và sau cùng thực hiện thao tác cài đặt.
Khi chạy script này, bạn sẽ nhận được đầu ra như sau:
break
và continue
Nếu bạn muốn kết thúc vòng lặp sớm hoặc bỏ qua một lần lặp cụ thể, bạn có thể sử dụng câu lệnh break
và continue
của shell. Chúng có thể được sử dụng trong bất kỳ vòng lặp nào.
Câu lệnh
break
được sử dụng để kết thúc vòng lặp hiện tại.Câu lệnh
continue
được sử dụng để bỏ qua một lần lặp.
💻 『Mã nguồn ví dụ』
💻 『Mã nguồn ví dụ』
Hàm
Cú pháp định nghĩa hàm trong bash như sau:
💡 Lưu ý:
- Từ khóa
function
có thể có hoặc không khi định nghĩa hàm.- Lệnh
return
được sử dụng để trả về giá trị từ hàm, giá trị trả về chỉ có thể là số nguyên (từ 0-255). Nếu không có lệnhreturn
, shell sẽ trả về kết quả của lệnh cuối cùng làm giá trị trả về của hàm.- Giá trị trả về của hàm có thể được lấy sau khi gọi hàm bằng biến
$?
.- Tất cả các hàm phải được định nghĩa trước khi sử dụng. Điều này có nghĩa là hàm phải được đặt ở đầu script, cho đến khi trình thông dịch shell gặp nó lần đầu tiên, sau đó mới có thể sử dụng hàm bằng cách gọi tên của nó.
💻 『Mã nguồn ví dụ』
Kết quả thực thi:
Tham số vị trí
Tham số vị trí là các biến được tạo ra khi gọi một hàm và truyền tham số cho nó.
Bảng biến tham số vị trí:
Biến | Mô tả |
---|---|
$0 | Tên script |
$1 … $9 | Tham số thứ 1 đến tham số thứ 9 |
${10} … | Tham số thứ 10 trở đi |
$* hoặc $@ | Tất cả các tham số trừ $0 |
$# | Số lượng tham số trừ $0 |
$FUNCNAME | Tên hàm (chỉ có giá trị bên trong hàm) |
💻 『Mã nguồn ví dụ』
Kết quả thực thi:
Chạy ./variable-demo4.sh hello world
, sau đó trong script, đọc tham số thứ nhất bằng $1
, tham số thứ hai bằng $2
…
Xử lý tham số của hàm
Ngoài ra, còn một số ký tự đặc biệt được sử dụng để xử lý tham số:
Xử lý tham số | Mô tả |
---|---|
$# | Trả về số lượng tham số |
$* | Trả về tất cả các tham số |
$$ | Trả về ID tiến trình hiện tại của script |
$! | Trả về ID của tiến trình cuối cùng chạy ở nền |
$@ | Trả về tất cả các tham số |
$- | Trả về các tùy chọn hiện tại của Shell, tương tự set |
$? | Trả về giá trị trả về của hàm |
💻 『Mã nguồn ví dụ』
Mở rộng Shell
Mở rộng xảy ra sau khi một dòng lệnh được chia thành các token. Nó là cơ chế để thực hiện các phép tính toán, lưu kết quả thực thi của lệnh, và nhiều hơn nữa.
Nếu bạn quan tâm, bạn có thể đọc thêm về mở rộng shell.
Mở rộng dấu ngoặc nhọn
Mở rộng dấu ngoặc nhọn cho phép tạo ra bất kỳ chuỗi nào. Nó tương tự như mở rộng tên tệp , ví dụ:
Mở rộng dấu ngoặc nhọn cũng có thể được sử dụng để tạo ra một phạm vi có thể lặp lại.
Thay thế lệnh
Thay thế lệnh cho phép chúng ta đánh giá một lệnh và thay thế kết quả của nó vào một lệnh khác hoặc một biểu thức gán giá trị. Khi một lệnh được bao quanh bởi “ hoặc $()
, thay thế lệnh sẽ được thực thi. Ví dụ:
Mở rộng số học
Trong bash, thực hiện các phép tính toán là rất tiện lợi. Biểu thức số học phải được bao quanh bởi $(())
. Cú pháp mở rộng số học là:
Trong biểu thức số học, không cần sử dụng tiền tố $
cho biến:
Dấu nháy đơn và nháy kép
Dấu nháy đơn và nháy kép có một số khác biệt quan trọng. Trong dấu nháy kép, các tham chiếu biến hoặc thay thế lệnh sẽ được mở rộng. Trong dấu nháy đơn, không có mở rộng nào xảy ra. Ví dụ:
Khi biến cục bộ và biến môi trường chứa khoảng trắng, việc mở rộng chúng trong dấu nháy đơn cần được chú ý. Ví dụ:
Khi gọi lệnh echo
lần thứ nhất, nó nhận 5 tham số riêng biệt - $INPUT
được chia thành các từ riêng biệt và echo
in ra một khoảng trắng giữa mỗi từ. Trong trường hợp thứ hai, lệnh echo
chỉ nhận một tham số duy nhất (giá trị $INPUT
đầy đủ, bao gồm cả khoảng trắng).
Dưới đây là một ví dụ nghiêm trọng hơn:
Mặc dù vấn đề này có thể được giải quyết bằng cách đổi tên FILE thành Favorite-Things.txt
, nhưng nếu giá trị này đến từ một biến môi trường, từ một tham số vị trí, hoặc từ một lệnh khác (find
, cat
, v.v.), thì sao? Do đó, nếu đầu vào có thể chứa khoảng trắng, hãy luôn luôn đặt biểu thức trong dấu nháy.
Luồng và Chuyển hướng
Bash có các công cụ mạnh mẽ để xử lý việc làm việc chung giữa các chương trình. Sử dụng luồng, chúng ta có thể gửi đầu ra của một chương trình đến một chương trình hoặc tệp tin khác, từ đó, chúng ta có thể dễ dàng ghi nhật ký hoặc thực hiện các công việc khác mà chúng ta muốn.
Ống (Pipe) cho phép chúng ta tạo ra một dây chuyền truyền tải, làm cho việc kiểm soát thực thi của chương trình trở nên khả thi.
Việc học cách sử dụng các công cụ mạnh mẽ và cao cấp này là rất quan trọng.
Luồng vào, luồng ra
Bash nhận đầu vào và tạo ra đầu ra dưới dạng chuỗi ký tự hoặc luồng ký tự. Các luồng này có thể được định tuyến đến tệp tin hoặc luồng khác.
Có ba mô tả tệp tin:
Mã | Mô tả | Mô tả |
---|---|---|
0 | stdin | Đầu vào chuẩn |
1 | stdout | Đầu ra chuẩn |
2 | stderr | Đầu ra lỗi |
Chuyển hướng
Chuyển hướng (Redirect) cho phép chúng ta kiểm soát nguồn đầu vào của một lệnh đến đâu và đầu ra kết quả đến đâu. Các toán tử sau được sử dụng trong việc Chuyển hướng luồng điều khiển:
Toán tử | Mô tả |
---|---|
> | Chuyển hướng đầu ra |
&> | Chuyển hướng đầu ra và đầu ra lỗi |
&>> | Chuyển hướng đầu ra và đầu ra lỗi dưới dạng gắn thêm |
< | Chuyển hướng đầu vào |
<< | Cú pháp Here Document |
<<< | Chuỗi Here |
Dưới đây là một số ví dụ về việc sử dụng chuyển hướng:
Tệp tin /dev/null
Nếu muốn thực thi một lệnh nhưng không muốn hiển thị kết quả đầu ra trên màn hình, bạn có thể Chuyển hướng đầu ra đến /dev/null:
/dev/null là một tệp tin đặc biệt, nội dung được ghi vào nó sẽ bị loại bỏ; nếu cố gắng đọc nội dung từ tệp tin này, bạn sẽ không đọc được gì cả. Tuy nhiên, tệp tin /dev/null rất hữu ích, việc Chuyển hướng đầu ra của lệnh đến nó sẽ có hiệu quả “vô hiệu hóa đầu ra”.
Nếu muốn ẩn stdout và stderr, bạn có thể viết như sau:
Debug
Shell cung cấp các công cụ để gỡ lỗi các tập lệnh.
Nếu bạn muốn chạy một tập lệnh trong chế độ gỡ lỗi, bạn có thể sử dụng một tùy chọn đặc biệt trong shebang của nó:
#!/bin/bash options
options là một số tùy chọn có thể thay đổi hành vi của shell. Dưới đây là một số tùy chọn có thể hữu ích cho bạn:
Ngắn gọn | Tên | Mô tả |
---|---|---|
-f | noglob | Vô hiệu hóa mở rộng tên tệp (globbing) |
-i | interactive | Chạy tập lệnh trong chế độ tương tác |
-n | noexec | Đọc các lệnh nhưng không thực thi (kiểm tra cú pháp) |
-t | — | Thoát sau khi thực thi lệnh đầu tiên |
-v | verbose | In ra mỗi lệnh trước khi thực thi nó |
-x | xtrace | In ra mỗi lệnh và các tham số mở rộng của nó trước khi thực thi |
Ví dụ, nếu chúng ta chỉ định -x
trong tập lệnh của mình, như sau:
Điều này sẽ in ra giá trị của biến và một số thông tin hữu ích khác trên stdout
:
Đôi khi chúng ta chỉ cần gỡ lỗi một phần của tập lệnh. Trong trường hợp này, sử dụng lệnh set
sẽ rất tiện lợi. Lệnh này cho phép bạn bật hoặc tắt các tùy chọn. Sử dụng -
để bật tùy chọn và +
để tắt tùy chọn:
💻 『Mã nguồn mẫu』
Tài liệu tham khảo
- awesome-shell - Danh sách tài nguyên về shell
- awesome-bash - Danh sách tài nguyên về bash
- bash-handbook
- bash-guide - Hướng dẫn cơ bản về cách sử dụng bash
- bash-it - Một framework đáng tin cậy để sử dụng hàng ngày, phát triển và duy trì các tập lệnh shell và các lệnh tùy chỉnh của bạn
- dotfiles.github.io - Cung cấp các bộ sưu tập dotfiles cho bash và các shell khác, cũng như liên kết đến các framework shell
- Hướng dẫn Shell của tutorialspoint
- shellcheck - Một công cụ phân tích tĩnh cho shell script, thực chất là một công cụ lint cho bash/sh/zsh.
Cuối cùng, trên Stack Overflow, có rất nhiều câu hỏi về bash trong thẻ bash, bạn có thể học hỏi từ những câu hỏi đó và cũng có thể đặt câu hỏi của riêng bạn khi gặp vấn đề.