Sự không nhất quán phần lớn là do lý do lịch sử.
Việc sử dụng dấu ngoặc làm lệnh điều kiện được đưa ra sau khi sử dụng dấu ngoặc trong các mẫu ký tự đại diện. Vì vậy, tại thời điểm đó [ -n foo ]
xuất hiện, [foo]
đã có nghĩa là một tập tin có tên là f
hay o
. Mặc dù ít sử dụng toán tử ngoặc trong thực tế sẽ mâu thuẫn với sử dụng thực tế của dấu ngoặc trong ký tự đại diện, các tác giả đã chọn không mạo hiểm phá vỡ các tập lệnh hiện có bằng cách thay đổi cú pháp. Sự lựa chọn thiết kế này cũng làm cho việc thực hiện dễ dàng hơn: ban đầu [
được thực hiện như một lệnh bên ngoài, điều này không thể được thực hiện nếu không gian sau [
đó là tùy chọn. (Các hệ thống hiện đại vẫn có [
một lệnh bên ngoài nhưng hầu như tất cả các hệ vỏ hiện đại cũng được tích hợp sẵn.)
Vì những lý do tương tự, mã làm việc trên mạng của bạn thực sự không chính xác trong hầu hết các trường hợp. $1
không có nghĩa là giá trị của tham số 1 QUAN: nó có nghĩa là lấy giá trị của tham số 1, chia nó thành các từ riêng biệt ở khoảng trắng (hoặc bất kể giá trị của IFS
nó là gì) và diễn giải từng từ dưới dạng mô hình toàn cầu. Cách viết ra giá trị của tham số 11 yêu cầu dấu ngoặc kép : "$1"
. Xem Khi nào cần trích dẫn kép? cho nitty-gritty. Bạn không cần phải hiểu điều này; tất cả những gì bạn cần nhớ là: luôn đặt dấu ngoặc kép xung quanh các thay thế "$foo"
và thay thế lệnh"$(foo)"
. Như vậy:
if [ -n "$1" ]; then …
Trong bash, ksh và zsh, nhưng không phải trong sh đơn giản, bạn cũng có thể sử dụng dấu ngoặc kép. Dấu ngoặc đơn [ … ]
được phân tích cú pháp như một lệnh thông thường (và thực sự [
là một lệnh thông thường, mặc dù thường được xây dựng). Dấu ngoặc kép là một cấu trúc cú pháp riêng biệt và bạn có thể bỏ qua dấu ngoặc kép hầu hết thời gian.
if [[ -n $1 ]]; then …
Tuy nhiên, có một ngoại lệ: [[ "$foo" = "$bar" ]]
để kiểm tra xem hai biến có cùng giá trị yêu cầu dấu ngoặc kép $bar
hay không, nếu không thì $bar
được hiểu là mẫu ký tự đại diện. Một lần nữa, thay vì nhớ các chi tiết, bạn cũng có thể sử dụng dấu ngoặc kép mọi lúc.