Computer >> Máy Tính >  >> Lập trình >> Lập trình BASH

Cách lập trình với Bash:Toán tử logic và mở rộng shell

Bash là một ngôn ngữ lập trình mạnh mẽ, được thiết kế hoàn hảo để sử dụng trên dòng lệnh và trong các tập lệnh shell. Loạt bài ba phần này (dựa trên khóa học tự học Linux ba tập của tôi) khám phá cách sử dụng Bash làm ngôn ngữ lập trình trên giao diện dòng lệnh (CLI).

Bài viết đầu tiên đã khám phá một số lập trình dòng lệnh đơn giản với Bash, bao gồm cả việc sử dụng các biến và toán tử điều khiển. Bài viết thứ hai này xem xét các loại toán tử logic tệp, chuỗi, số và linh tinh cung cấp logic điều khiển luồng thực thi và các loại mở rộng shell khác nhau trong Bash. Bài viết thứ ba và cuối cùng trong loạt bài này sẽ khám phá cho , trong khi cho đến khi vòng lặp cho phép các hoạt động lặp lại.

Các toán tử logic là cơ sở để đưa ra các quyết định trong một chương trình và thực hiện các tập lệnh khác nhau dựa trên các quyết định đó. Điều này đôi khi được gọi là kiểm soát luồng.

Toán tử logic

Bash có một tập hợp lớn các toán tử logic có thể được sử dụng trong các biểu thức điều kiện. Dạng cơ bản nhất của if cấu trúc điều khiển kiểm tra một điều kiện và sau đó thực hiện một danh sách các câu lệnh chương trình nếu điều kiện là đúng. Có ba loại toán tử:toán tử tệp, số và không phải số. Mỗi toán tử trả về true (0) nếu điều kiện được đáp ứng và false (1) nếu điều kiện không được đáp ứng.

Cú pháp hàm của các toán tử so sánh này là một hoặc hai đối số với một toán tử được đặt trong dấu ngoặc vuông, theo sau là danh sách các câu lệnh chương trình được thực thi nếu điều kiện là đúng và danh sách tùy chọn các câu lệnh chương trình nếu điều kiện là sai :

 if [arg1 operator arg2]; sau đó liệt kê 
hoặc
if [arg1 operator arg2]; sau đó liệt kê; danh sách khác; fi

Các khoảng trắng trong so sánh được yêu cầu như được hiển thị. Dấu ngoặc vuông đơn, [] , là các ký hiệu Bash truyền thống tương đương với test lệnh:

 if test arg1 operator arg2 ; then list 

Ngoài ra còn có một cú pháp mới hơn cung cấp một số lợi thế và một số sysadmins thích hơn. Định dạng này ít tương thích hơn một chút với các phiên bản khác nhau của Bash và các trình bao khác, chẳng hạn như ksh (trình bao Korn). Nó trông giống như:

 if [[ arg1 operator arg2 ]] ; then list 

Toán tử tệp

Toán tử tệp là một tập hợp các toán tử logic mạnh mẽ trong Bash. Hình 1 liệt kê hơn 20 toán tử khác nhau mà Bash có thể thực hiện trên các tệp. Tôi sử dụng chúng khá thường xuyên trong các tập lệnh của mình.

Toán tử Mô tả
-a tên tệp Đúng nếu tệp tồn tại; nó có thể trống hoặc có một số nội dung nhưng, miễn là nó tồn tại, điều này sẽ đúng
-b tên tệp Đúng nếu tệp tồn tại và là một khối tệp đặc biệt, chẳng hạn như ổ cứng như / dev / sda hoặc / dev / sda1
-c tên tệp Đúng nếu tệp tồn tại và là tệp ký tự đặc biệt, chẳng hạn như thiết bị TTY như / dev / TTY1
-d tên tệp Đúng nếu tệp tồn tại và là một thư mục
-e tên tệp Đúng nếu tệp tồn tại; điều này giống với -a trên
-f tên tệp Đúng nếu tệp tồn tại và là tệp thông thường, trái ngược với thư mục, tệp đặc biệt của thiết bị hoặc liên kết, trong số những tệp khác
-g tên tệp Đúng nếu tệp tồn tại và là set-group-id , SETGID
-h tên tệp Đúng nếu tệp tồn tại và là một liên kết tượng trưng
-k tên tệp Đúng nếu tệp tồn tại và bit "dính" của nó được đặt
-p tên tệp Đúng nếu tệp tồn tại và là một đường ống được đặt tên (FIFO)
-r tên tệp Đúng nếu tệp tồn tại và có thể đọc được, tức là có bộ bit đọc
-s tên tệp Đúng nếu tệp tồn tại và có kích thước lớn hơn 0; một tệp tồn tại nhưng có kích thước bằng 0 sẽ trả về false
-t fd Đúng nếu trình mô tả tệp fd đang mở và tham chiếu đến một thiết bị đầu cuối
-u tên tệp Đúng nếu tệp tồn tại và set-user-id của nó bit được đặt
-w tên tệp Đúng nếu tệp tồn tại và có thể ghi được
-x tên tệp Đúng nếu tệp tồn tại và có thể thực thi được
-Tên tệp G Đúng nếu tệp tồn tại và thuộc sở hữu của ID nhóm hiệu quả
-L tên tệp Đúng nếu tệp tồn tại và là một liên kết tượng trưng
-N tên tệp Đúng nếu tệp tồn tại và đã được sửa đổi kể từ lần đọc cuối cùng
-Tên tệp Đúng nếu tệp tồn tại và thuộc sở hữu của ID người dùng hiệu quả
-S tên tệp Đúng nếu tệp tồn tại và là ổ cắm
file1 -ef file2 Đúng nếu file1 và file2 tham chiếu đến cùng một thiết bị và số iNode
file1 -nt file2 Đúng nếu tệp1 mới hơn (theo ngày sửa đổi) so với tệp 2 hoặc nếu tệp1 tồn tại và tệp2 thì không
file1 -ot file2 Đúng nếu tệp1 cũ hơn tệp2 hoặc nếu tệp2 tồn tại và tệp1 thì không

Hình. 1:Các toán tử tệp Bash

Ví dụ:bắt đầu bằng cách kiểm tra sự tồn tại của tệp:

 [student @ studentvm1 testdir] $ File ="TestFile1"; if [-e $ File]; sau đó echo "Tệp $ File tồn tại."; else echo "Tệp $ File không tồn tại."; fi 
Tệp TestFile1 không tồn tại.
[student @ studentvm1 testdir] $

Tiếp theo, tạo một tệp để thử nghiệm có tên TestFile1 . Hiện tại, nó không cần phải chứa bất kỳ dữ liệu nào:

 [student@studentvm1 testdir]$ touch TestFile1 

Dễ dàng thay đổi giá trị của $ File thay vì một chuỗi văn bản cho tên tệp ở nhiều vị trí trong chương trình CLI ngắn này:

 [student @ studentvm1 testdir] $ File ="TestFile1"; if [-e $ File]; sau đó echo "Tệp $ File tồn tại."; else echo "Tệp $ File không tồn tại."; fi 
Tệp TestFile1 tồn tại.
[student @ studentvm1 testdir] $

Bây giờ, hãy chạy thử nghiệm để xác định xem một tệp có tồn tại và có độ dài khác 0 hay không, nghĩa là nó có chứa dữ liệu. Bạn muốn kiểm tra ba điều kiện:1. tệp không tồn tại; 2. tệp tồn tại và trống; và 3. tệp tồn tại và chứa dữ liệu. Do đó, bạn cần một bộ kiểm tra phức tạp hơn — sử dụng elif khổ thơ trong if-elif-else cấu trúc để kiểm tra tất cả các điều kiện:

 [student @ studentvm1 testdir] $ File ="TestFile1"; if [-s $ File]; sau đó echo "$ File tồn tại và chứa dữ liệu."; fi 
[student @ studentvm1 testdir] $

Trong trường hợp này, tệp tồn tại nhưng không chứa bất kỳ dữ liệu nào. Thêm một số dữ liệu và thử lại:

 [student @ studentvm1 testdir] $ File ="TestFile1"; echo "Đây là tệp $ File"> $ File; if [-s $ File]; sau đó echo "$ File tồn tại và chứa dữ liệu."; fi 
TestFile1 tồn tại và chứa dữ liệu.
[student @ studentvm1 testdir] $

Điều đó hoạt động, nhưng nó chỉ thực sự chính xác đối với một điều kiện cụ thể trong số ba điều kiện có thể xảy ra. Thêm khác stanza để bạn có thể chính xác hơn phần nào và xóa tệp để bạn có thể kiểm tra đầy đủ mã mới này:

 [student @ studentvm1 testdir] $ File ="TestFile1"; rm $ Tệp; if [-s $ File]; sau đó echo "$ File tồn tại và chứa dữ liệu."; else echo "$ File không tồn tại hoặc trống."; fi 
TestFile1 không tồn tại hoặc trống.

Bây giờ, hãy tạo một tệp trống để kiểm tra:

 [student @ studentvm1 testdir] $ File ="TestFile1"; chạm vào $ File; if [-s $ File]; sau đó echo "$ File tồn tại và chứa dữ liệu."; else echo "$ File không tồn tại hoặc trống."; fi 
TestFile1 không tồn tại hoặc trống.

Thêm một số nội dung vào tệp và kiểm tra lại:

 [student @ studentvm1 testdir] $ File ="TestFile1"; echo "Đây là tệp $ File"> $ File; if [-s $ File]; sau đó echo "$ File tồn tại và chứa dữ liệu."; else echo "$ File không tồn tại hoặc trống."; fi 
TestFile1 tồn tại và chứa dữ liệu.

Bây giờ, hãy thêm elif khổ thơ để phân biệt giữa tệp không tồn tại và tệp trống:

 [student @ studentvm1 testdir] $ File ="TestFile1"; chạm vào $ File; if [-s $ File]; sau đó echo "$ File tồn tại và chứa dữ liệu."; elif [-e $ File]; sau đó echo "$ File tồn tại và trống."; khác echo "$ File không tồn tại."; fi 
TestFile1 tồn tại và trống.
[student @ studentvm1 testdir] $ File ="TestFile1"; echo "Đây là $ File"> $ File; if [-s $ File]; sau đó echo "$ File tồn tại và chứa dữ liệu."; elif [-e $ File]; sau đó echo "$ File tồn tại và trống."; khác echo "$ File không tồn tại."; fi
TestFile1 tồn tại và chứa dữ liệu.
[student @ studentvm1 testdir] $

Bây giờ bạn có một chương trình Bash CLI có thể kiểm tra ba điều kiện khác nhau này… nhưng khả năng là vô tận.

Sẽ dễ dàng nhìn thấy cấu trúc logic của các lệnh ghép phức tạp hơn nếu bạn sắp xếp các câu lệnh chương trình giống như bạn làm trong một tập lệnh mà bạn có thể lưu trong một tệp. Hình 2 cho thấy nó sẽ trông như thế nào. Thụt lề của câu lệnh chương trình trong mỗi khổ của if-elif-else cấu trúc giúp làm rõ logic.

 File ="TestFile1" 
echo "Đây là $ File"> $ File
nếu [-s $ File]
thì
echo "$ File tồn tại và chứa dữ liệu . "
elif [-e $ File]
then
echo "$ File tồn tại và trống."
else
echo "$ File không tồn tại."
fi

Hình. 2:Chương trình dòng lệnh được viết lại giống như nó sẽ xuất hiện trong tập lệnh

Logic phức tạp này quá dài đối với hầu hết các chương trình CLI. Mặc dù bất kỳ lệnh tích hợp sẵn nào của Linux hoặc Bash đều có thể được sử dụng trong các chương trình CLI, vì các chương trình CLI ngày càng dài và phức tạp hơn, việc tạo một tập lệnh được lưu trữ trong một tệp sẽ có ý nghĩa hơn và có thể được thực thi bất cứ lúc nào, ngay bây giờ hoặc trong tương lai.

Toán tử so sánh chuỗi

Toán tử so sánh chuỗi cho phép so sánh các chuỗi ký tự chữ và số. Chỉ có một số toán tử trong số này, được liệt kê trong Hình 3.

Toán tử Mô tả
-z string Đúng nếu độ dài của chuỗi bằng 0
-n chuỗi Đúng nếu độ dài của chuỗi khác 0
string1 ==string2

hoặc

string1 =string2
Đúng nếu các chuỗi bằng nhau; một = nên được sử dụng với lệnh kiểm tra sự phù hợp của POSIX. Khi được sử dụng với [[ lệnh này thực hiện đối sánh mẫu như được mô tả ở trên (lệnh ghép).
string1! =string2 Đúng nếu các chuỗi không bằng nhau
string1 Đúng nếu string1 sắp xếp trước string2 về mặt từ vựng (đề cập đến các trình tự sắp xếp theo ngôn ngữ cụ thể cho tất cả các ký tự chữ và số và ký tự đặc biệt)
string1> string2 Đúng nếu string1 sắp xếp sau string2 về mặt từ vựng

Hình. 3:Toán tử logic chuỗi băm

Đầu tiên, hãy nhìn vào độ dài chuỗi. Các báo giá xung quanh $ MyVar trong sự so sánh phải có để sự so sánh hoạt động. (Bạn vẫn phải làm việc trong ~ / testdir .)

 [student @ studentvm1 testdir] $ MyVar =""; if [-z ""]; sau đó echo "MyVar có độ dài bằng không."; else echo "MyVar chứa dữ liệu"; fi 
MyVar có độ dài bằng không.
[student @ studentvm1 testdir] $ MyVar ="Văn bản ngẫu nhiên"; if [-z ""]; sau đó echo "MyVar có độ dài bằng không."; else echo "MyVar chứa dữ liệu"; fi
MyVar có độ dài bằng không.

Bạn cũng có thể làm theo cách này:

 [student @ studentvm1 testdir] $ MyVar ="Văn bản ngẫu nhiên"; if [-n "$ MyVar"]; sau đó echo "MyVar chứa dữ liệu."; else echo "MyVar có độ dài bằng 0"; fi 
MyVar chứa dữ liệu.
[student @ studentvm1 testdir] $ MyVar =""; if [-n "$ MyVar"]; sau đó echo "MyVar chứa dữ liệu."; else echo "MyVar có độ dài bằng 0"; fi
MyVar có độ dài bằng 0

Đôi khi bạn có thể cần biết độ dài chính xác của một chuỗi. Đây không phải là một so sánh, nhưng nó có liên quan. Thật không may, không có cách nào đơn giản để xác định độ dài của một chuỗi. Có một số cách để làm điều đó, nhưng tôi nghĩ rằng sử dụng expr lệnh (đánh giá biểu thức) là dễ nhất. Đọc trang người đàn ông cho expr để biết thêm về những gì nó có thể làm. Lưu ý rằng bắt buộc phải có dấu ngoặc kép xung quanh chuỗi hoặc biến mà bạn đang thử nghiệm.

 [student @ studentvm1 testdir] $ MyVar =""; expr length "$ MyVar" 
0
[student @ studentvm1 testdir] $ MyVar ="Cái này dài bao nhiêu?"; expr length "$ MyVar"
17
[student @ studentvm1 testdir] $ expr length "Chúng tôi cũng có thể tìm độ dài của một chuỗi ký tự cũng như một biến."
70
>

Về các toán tử so sánh, tôi sử dụng rất nhiều thử nghiệm trong các tập lệnh của mình để xác định xem hai chuỗi có bằng nhau (tức là giống hệt nhau) hay không. Tôi sử dụng phiên bản không phải POSIX của toán tử so sánh này:

 [student @ studentvm1 testdir] $ Var1 ="Xin chào Thế giới"; Var2 ="Xin chào Thế giới"; if ["$ Var1" =="$ Var2"]; sau đó echo "Var1 khớp với Var2"; khác echo "Var1 và Var2 không khớp."; fi 
Var1 khớp với Var2
[student @ studentvm1 testdir] $ Var1 ="Hello World"; Var2 ="Xin chào thế giới"; if ["$ Var1" =="$ Var2"]; sau đó echo "Var1 khớp với Var2"; khác echo "Var1 và Var2 không khớp."; fi
Var1 và Var2 không khớp.

Hãy tự mình thử nghiệm thêm một số để thử các toán tử này.

Toán tử so sánh số

Toán tử số thực hiện so sánh giữa hai đối số số. Giống như các lớp toán tử khác, hầu hết đều dễ hiểu.

Toán tử Mô tả
arg1 -eq arg2 Đúng nếu arg1 bằng arg2
arg1 -ne arg2 Đúng nếu arg1 không bằng arg2
arg1 -lt arg2 Đúng nếu arg1 nhỏ hơn arg2
arg1 -le arg2 Đúng nếu arg1 nhỏ hơn hoặc bằng arg2
arg1 -gt arg2 Đúng nếu arg1 lớn hơn arg2
arg1 -ge arg2 Đúng nếu arg1 lớn hơn hoặc bằng arg2

Hình. 4:Toán tử logic so sánh số băm

Dưới đây là một số ví dụ đơn giản. Trường hợp đầu tiên đặt biến $ X thành 1, sau đó kiểm tra xem $ X bằng 1. Trong trường hợp thứ hai, X được đặt thành 0, vì vậy so sánh không đúng.

 [student @ studentvm1 testdir] $ X =1; nếu [$ X -eq 1]; sau đó echo "X bằng 1"; else echo "X không bằng 1"; fi 
X bằng 1
[student @ studentvm1 testdir] $ X =0; nếu [$ X -eq 1]; sau đó echo "X bằng 1"; else echo "X không bằng 1"; fi
X không bằng 1
[student @ studentvm1 testdir] $

Hãy thử một số thử nghiệm khác của riêng bạn.

Các toán tử khác

Các toán tử linh tinh này cho biết liệu một tùy chọn shell được đặt hay một biến shell có một giá trị, nhưng nó không phát hiện ra giá trị của biến, chỉ là nó có một giá trị hay không.

Toán tử Mô tả
-o optname Đúng nếu optname tùy chọn shell được bật (xem danh sách các tùy chọn trong mô tả của -o tùy chọn cho nội trang bộ Bash trong trang Bash man)
-v varname Đúng nếu biến shell varname được đặt (đã được gán giá trị)
-R varname Đúng nếu biến shell varname được đặt và là một tham chiếu tên

Hình. 5:Các toán tử logic Bash khác

Hãy tự mình thử nghiệm để thử các toán tử này.

Mở rộng

Bash hỗ trợ một số kiểu mở rộng và thay thế có thể khá hữu ích. Theo trang Bash man, Bash có bảy dạng mở rộng. Bài viết này xem xét năm trong số chúng:mở rộng dấu ngã, mở rộng số học, mở rộng tên đường dẫn, mở rộng dấu ngoặc nhọn và thay thế lệnh.

Mở rộng dấu ngoặc nhọn

Mở rộng dấu ngoặc nhọn là một phương pháp tạo chuỗi tùy ý. (Công cụ này được sử dụng bên dưới để tạo một số lượng lớn tệp cho các thử nghiệm với các ký tự mẫu đặc biệt.) Mở rộng dấu ngoặc nhọn có thể được sử dụng để tạo danh sách các chuỗi tùy ý và chèn chúng vào một vị trí cụ thể trong một chuỗi tĩnh bao quanh hoặc ở một trong hai đầu của chuỗi tĩnh. Điều này có thể khó hình dung, vì vậy tốt nhất là bạn cứ làm.

Đầu tiên, đây là những gì mà một mở rộng dấu ngoặc nhọn thực hiện:

 [student @ studentvm1 testdir] $ echo {string1, string2, string3} 
string1 string2 string3

Chà, điều đó không hữu ích lắm phải không? Nhưng hãy xem điều gì sẽ xảy ra khi bạn sử dụng nó hơi khác một chút:

 [student @ studentvm1 testdir] $ echo "Xin chào" {David, Jen, Rikki, Jason}. 
Xin chào David. Xin chào Jen. Xin chào Rikki. Xin chào Jason.

Điều đó trông giống như một thứ gì đó hữu ích — nó có thể tiết kiệm rất nhiều công việc đánh máy. Bây giờ hãy thử cái này:

 [student @ studentvm1 testdir] $ echo b {ed, olt, ar} s 
thanh bu lông trên giường

Tôi có thể tiếp tục, nhưng bạn hiểu rồi đấy.

Mở rộng dấu nghiêng

Có thể cho rằng, phần mở rộng phổ biến nhất là dấu ngã ( ~ ) sự bành trướng. Khi bạn sử dụng điều này trong một lệnh như cd ~ / Documents , Bash shell mở rộng nó như một lối tắt đến thư mục chính đầy đủ của người dùng.

Sử dụng các chương trình Bash này để quan sát các tác động của việc mở rộng dấu ngã:

 [student @ studentvm1 testdir] $ echo ~ 
/ home / student
[student @ studentvm1 testdir] $ echo ~ / Documents
/ home / student / Documents
[ student @ studentvm1 testdir] $ Var1 =~ / Tài liệu; echo $ Var1; cd $ Var1
/ home / student / Documents
[student @ studentvm1 Documents] $

Mở rộng tên đường dẫn

Mở rộng tên đường dẫn là một thuật ngữ ưa thích mở rộng các mô hình lấp lánh tệp, sử dụng các ký tự ? * , thành tên đầy đủ của các thư mục phù hợp với mẫu. Tệp liên kết đề cập đến các ký tự mẫu đặc biệt cho phép linh hoạt đáng kể trong việc đối sánh tên tệp, thư mục và các chuỗi khác khi thực hiện các hành động khác nhau. Các ký tự mẫu đặc biệt này cho phép khớp các ký tự đơn, nhiều hoặc cụ thể trong một chuỗi.

  • ? - Chỉ khớp một trong bất kỳ ký tự nào ở vị trí được chỉ định trong chuỗi
  • * - Đối sánh không hoặc nhiều ký tự bất kỳ ở vị trí được chỉ định trong chuỗi

Mở rộng này được áp dụng cho các tên thư mục phù hợp. Để xem cách này hoạt động, hãy đảm bảo rằng testdir là thư mục làm việc hiện tại (PWD) và bắt đầu bằng một danh sách đơn giản (nội dung trong thư mục chính của tôi sẽ khác với thư mục của bạn):

 [student @ studentvm1 testdir] $ ls 
chap6 cpuHog.dos dmesg1.txt Tài liệu Music softlink1 testdir6 Videos
chap7 cpuHog.Linux dmesg2.txt Tải xuống Ảnh Mẫu testdir
testdir cpuHog.mac dmesg3.txt file005 Public testdir tmp
cpuHog Desktop dmesg.txt link3 random.txt testdir1 umask.test
[student @ studentvm1 testdir] $

Bây giờ, hãy liệt kê các thư mục bắt đầu bằng Do , testdir / Tài liệu testdir / Tải xuống :

 Documents:
Directory01 file07 file15 test02 test10 test20 testfile13 TextFiles
Directory02 file08 file16 test03 test11 testfile01 testfile14
file01 file09 file17 test04 test12 testfile04 testfile15
file02 file10 file18 test05 test13 testfile05 testfile16
file03 file11 file19 test06 test14 testfile09 testfile17
file04 file12 file20 test07 test15 testfile10 testfile18
file05 file13 Student1.txt test08 test16 testfile11 testfile19
file06 file14 test01 test09 test18 testfile12 testfile20
Tải xuống
:
[student @ studentvm1 testdir] $

Chà, điều đó đã không làm những gì bạn muốn. Nó liệt kê nội dung của các thư mục bắt đầu bằng Do . Để chỉ liệt kê các thư mục chứ không liệt kê nội dung của chúng, hãy sử dụng -d tùy chọn.

 [student @ studentvm1 testdir] $ ls -d Do * 
Tải xuống tài liệu
[student @ studentvm1 testdir] $

Trong cả hai trường hợp, Bash shell mở rộng Do * mẫu vào tên của hai thư mục phù hợp với mẫu. Nhưng điều gì sẽ xảy ra nếu cũng có các tệp phù hợp với mẫu?

 [student @ studentvm1 testdir] $ touch Downtown; ls -d Do * 
Tải xuống tài liệu Trung tâm thành phố
[student @ studentvm1 testdir] $

Điều này cũng hiển thị tệp. Vì vậy, bất kỳ tệp nào phù hợp với mẫu cũng được mở rộng thành tên đầy đủ của chúng.

Thay thế lệnh

Thay thế lệnh là một dạng mở rộng cho phép dòng dữ liệu STDOUT của một lệnh được sử dụng làm đối số của lệnh khác; ví dụ, dưới dạng danh sách các mục sẽ được xử lý trong một vòng lặp. Trang Bash man cho biết:"Thay thế lệnh cho phép đầu ra của một lệnh để thay thế tên lệnh." Tôi thấy điều đó là chính xác nếu hơi thiếu sót.

Có hai hình thức thay thế này, `lệnh` $ (lệnh) . Ở dạng cũ hơn sử dụng tics trở lại ( ` ), sử dụng dấu gạch chéo ngược ( \ ) trong lệnh vẫn giữ nguyên nghĩa đen của nó. Tuy nhiên, khi nó được sử dụng ở dạng dấu ngoặc đơn mới hơn, dấu gạch chéo ngược sẽ mang ý nghĩa của nó như một ký tự đặc biệt. Cũng lưu ý rằng biểu mẫu ngoặc đơn chỉ sử dụng các dấu ngoặc đơn để mở và đóng câu lệnh.

Tôi thường sử dụng khả năng này trong các chương trình và tập lệnh dòng lệnh trong đó kết quả của một lệnh có thể được sử dụng làm đối số cho một lệnh khác.

Bắt đầu với một ví dụ rất đơn giản sử dụng cả hai dạng mở rộng này (một lần nữa, hãy đảm bảo rằng testdir là NKT):

 [student @ studentvm1 testdir] $ echo "Ngày của những ngày sau là` ngày` "
Ngày của những ngày cuối là Chủ nhật ngày 7 tháng 4 14:42:46 EDT 2019
[student @ studentvm1 testdir] $ echo" Những ngày cuối cùng ngày là $ (date) "
Ngày của ngày hôm nay là Chủ nhật, ngày 7 tháng 4 14:42:59 EDT 2019
[student @ studentvm1 testdir] $

-w tùy chọn cho seq tiện ích thêm các số không ở đầu vào các số được tạo để chúng có cùng độ rộng, tức là cùng một số chữ số bất kể giá trị là bao nhiêu. Điều này giúp bạn sắp xếp chúng theo thứ tự số dễ dàng hơn.

seq tiện ích được sử dụng để tạo một chuỗi số:

 [student @ studentvm1 testdir] $ seq 5 
1
2
3
4
5
[student @ studentvm1 testdir] $ echo ` seq 5`
1 2 3 4 5
[student @ studentvm1 testdir] $

Giờ đây, bạn có thể làm điều gì đó hữu ích hơn một chút, chẳng hạn như tạo một số lượng lớn các tệp trống để thử nghiệm:

 [student@studentvm1 testdir]$ for I in $(seq -w 5000) ; do touch file-$I ; done 

Trong cách sử dụng này, câu lệnh seq -w 5000 tạo danh sách các số từ một đến 5.000. Bằng cách sử dụng thay thế lệnh như một phần của for , danh sách các số được sử dụng bởi for câu lệnh để tạo phần số của tên tệp.

Khai triển số học

Bash có thể thực hiện phép toán số nguyên, nhưng nó khá cồng kềnh (như bạn sẽ thấy ngay sau đây). Cú pháp cho khai triển số học là $ ((biểu thức số học)) , sử dụng dấu ngoặc kép để mở và đóng biểu thức.

Khai triển số học hoạt động giống như thay thế lệnh trong chương trình shell hoặc tập lệnh; giá trị được tính toán từ biểu thức thay thế biểu thức để đánh giá thêm bởi shell.

Một lần nữa, hãy bắt đầu với một cái gì đó đơn giản:

 [student @ studentvm1 testdir] $ echo $ ((1 + 1)) 
2
[student @ studentvm1 testdir] $ Var1 =5; Var2 =7; Var3 =$ ((Var1 * Var2)); echo "Var 3 =$ Var3"
Var 3 =35

Phép chia sau cho kết quả bằng 0 vì kết quả sẽ là giá trị thập phân nhỏ hơn một:

 [student @ studentvm1 testdir] $ Var1 =5; Var2 =7; Var3 =$ ((Var1 / Var2)); echo "Var 3 =$ Var3" 
Var 3 =0

Đây là một phép tính đơn giản mà tôi thường làm trong một tập lệnh hoặc chương trình CLI cho tôi biết tổng bộ nhớ ảo mà tôi có trong một máy chủ Linux. miễn phí lệnh không cung cấp dữ liệu đó:

 [student @ studentvm1 testdir] $ RAM =`miễn phí | grep ^ Mem | awk '{print $ 2}' '; Swap =`miễn phí | grep ^ Hoán đổi | awk '{print $ 2}' '; echo "RAM =$ RAM và Swap =$ Swap"; echo "Tổng bộ nhớ ảo là $ ((RAM + Swap))"; 
RAM =4037080 và Swap =6291452
Tổng bộ nhớ ảo là 10328532

Tôi đã sử dụng ` ký tự để phân tách các phần mã được sử dụng để thay thế lệnh.

Tôi chủ yếu sử dụng mở rộng số học Bash để kiểm tra lượng tài nguyên hệ thống trong một tập lệnh và sau đó chọn đường dẫn thực thi chương trình dựa trên kết quả.

Tóm tắt

Bài viết này, bài thứ hai trong loạt bài này về ngôn ngữ lập trình Bash, đã khám phá tệp Bash, chuỗi, số và các toán tử logic khác cung cấp logic điều khiển luồng thực thi và các kiểu mở rộng shell khác nhau.

Bài thứ ba trong loạt bài này sẽ khám phá việc sử dụng các vòng lặp để thực hiện các loại hoạt động lặp khác nhau.