Tạo tập lệnh shell không thực sự là ngôn ngữ đầy đủ và nó phụ thuộc nhiều vào các lệnh bên ngoài khác để hoạt động.
Biến số sử dụng sigil có nghĩa là $
trước mặt chúng. Rất nhiều ngôn ngữ kịch bản lệnh shell sử dụng các biến sigils để giúp phân biệt giữa một chuỗi và một biến.
Ví dụ:
foo=foo_value
echo foo foo $foo foo
Sẽ in:
foo foo foo_value foo
Lưu ý rằng dấu ngoặc kép là không cần thiết cho việc vang tuyên bố cho các chuỗi.Cửa sổ hàng loạt vỏ rất giống:
set foo = foo_value
echo foo foo %foo% foo
Như bạn có thể thấy, sigil được sử dụng khi biến là giả sử để được mở rộng, nhưng không phải khi bạn định nghĩa nó. Đó là bởi vì vỏ Unix là các vỏ thông minh. Họ munge dòng lệnh trước khi nó được thực thi. Vỏ sẽ thay thế các biến môi trường trước thực hiện:
foo=bar
$foo="whose value is this" #Note the dollar sign!
echo The value of foo is $foo
echo The value of bar is $bar
này sẽ in ra:
The value of foo is foo
The value of bar is whose value is this
Nếu bạn sử dụng lệnh set -xv
, bạn sẽ thấy rằng $foo="whose value is this"
được mở rộng để bar=whose value is this"
trước khi nó được thực hiện.
Trong vỏ kiểu Bourne như Kornshell và BASH, tuyên bố if
không phải là ý của bạn. Lệnh if
thực thi câu lệnh và sẽ chọn mệnh đề nếu khoản nếu lệnh đó trả về giá trị bằng không. Ví dụ:
cat "foo" > my_file #Create a one line file with the string foo in it.
if grep -q "foo" my_file #grep command will return a zero exit code if it finds foo
then
echo "The string 'foo' is in file my_file"
fi
Lưu ý rằng nếu mệnh đề không phải là một câu lệnh logic. Đó là một lệnh thực tế được thực hiện.
Một nơi nào đó sớm trong phát triển Unix, lệnh test
đã được tạo. Bạn có thể thực hiện thử nghiệm người đàn ông và xem cách sử dụng nó.
Lệnh test
cho phép bạn làm điều này:
foo=3
bar=3
if test foo -eq bar
then
echo "foo and bar are equal"
else
echo "foo and bar are not equal"
fi
Nếu bạn làm điều này:
$ ls -li /bin/test /bin/[
Bạn sẽ thấy rằng một lệnh gọi [
thực sự tồn tại, và là một liên kết cứng đến test
lệnh. Điều này đã được tạo ra để làm cho một tuyên bố if
trông giống như một câu lệnh if bạn sẽ thấy trong các ngôn ngữ lập trình thường xuyên:
foo=3
bar=3
if [ foo -eq bar ]
then
echo "foo and bar are equal"
else
echo "foo and bar are not equal"
fi
chính xác kịch bản tương tự như trên, nhưng với [
thay vì test
.
Điều này giải thích tại sao bạn cần dấu gạch ngang trong nhiều thử nghiệm (đó là tham số cho lệnh test
và tham số bắt đầu bằng dấu gạch ngang!). Nó cũng giải thích tại sao bạn cần khoảng trống xung quanh [
và ]
. Đây là các lệnh Unix thực tế và các lệnh Unix phải có khoảng trắng xung quanh chúng, vì vậy trình bao có thể xử lý chúng.
Một vấn đề khác là tại sao vỏ có hai bộ kiểm tra khác nhau cho chuỗi và số. Đó là bởi vì chuỗi có thể không chứa gì ngoài chữ số, nhưng không thực sự là số. Ví dụ: nếu bạn thực hiện khoảng không quảng cáo, bạn có thể có một số bộ phận 001
và 01
. Bằng số, chúng bằng nhau, nhưng là chuỗi, chúng là hai chuỗi khác nhau. Không có cách nào cho kịch bản shell biết. Thay vào đó, bạn phải cho kịch bản lệnh biết nếu đó là so sánh số hoặc so sánh chuỗi.
Perl có vấn đề tương tự kể từ khi bạn không khai báo biến như số hoặc không phải số:
Shell Script Perl
Boolean Operator Numeric String Numeric String
=================== ======= ====== ======= ======
Equals -eq = == eq
Not Equals -ne != != ne
Greater Than -gt > > gt
Less Than -lt < < lt
Greater or Equals -ge >= >= ge
Less Than or Equals -le <= <= le
Bạn có thể thử một vài điều khác:
$ echo "*" #Echos the asterisk
$ echo * #No quotes: Prints all files in current directory
Thông báo một lần nữa vỏ nở*
trước khi thực hiện lệnh echo. Đây là sự khác biệt chính giữa một kịch bản lệnh shell và một ngôn ngữ lập trình điển hình. Shell đầu tiên mở rộng (điền vào các biến môi trường, thay thế glob, chạy các lệnh con) trước khi nó thực sự thực hiện lệnh.
set -xv
sẽ cho bạn biết lệnh nào đang được thực thi và cách vỏ mở rộng lệnh trước khi thực thi. Làm set +xv
sẽ tắt tính năng đó. Chơi xung quanh với điều đó, và bạn sẽ sớm hiểu vỏ một chút tốt hơn.
Tôi hy vọng sự thiếu hiểu biết của tôi sẽ được tha thứ: Tôi tương đối mới để lập trình bash, và cú pháp của nó không giống như bất kỳ ngôn ngữ lập trình nào khác mà tôi đã thấy. –