Mở rộng tham số
Câu trả lời rõ ràng là sử dụng một trong các hình thức mở rộng tham số đặc biệt:
: ${STATE?"Need to set STATE"}
: ${DEST:?"Need to set DEST non-empty"}
Hoặc, tốt hơn (xem phần trên 'Vị trí của dấu ngoặc kép' bên dưới):
: "${STATE?Need to set STATE}"
: "${DEST:?Need to set DEST non-empty}"
Biến thể đầu tiên (chỉ sử dụng ?
) yêu cầu STATE được đặt, nhưng STATE = "" (một chuỗi trống) là OK - không chính xác những gì bạn muốn, nhưng ký hiệu thay thế và cũ hơn.
Biến thể thứ hai (sử dụng :?
) yêu cầu DEST được đặt và không trống.
Nếu bạn cung cấp không có tin nhắn, shell sẽ cung cấp một tin nhắn mặc định.
Cấu ${var?}
trúc này có thể di chuyển trở lại Phiên bản 7 UNIX và Bourne Shell (1978 hoặc sau đó). Cấu ${var:?}
trúc gần đây hơn một chút: Tôi nghĩ rằng nó đã có trong System III UNIX vào khoảng năm 1981, nhưng nó có thể đã có trong PWB UNIX trước đó. Do đó, nó nằm trong Korn Shell và trong vỏ POSIX, bao gồm cả Bash.
Nó thường được ghi lại trong trang man của shell trong phần có tên là Mở rộng tham số . Ví dụ: bash
hướng dẫn sử dụng nói:
${parameter:?word}
Lỗi hiển thị nếu Null hoặc Unset. Nếu tham số là null hoặc không được đặt, việc mở rộng từ (hoặc thông báo cho hiệu ứng đó nếu không có từ) được ghi vào lỗi tiêu chuẩn và trình bao, nếu nó không tương tác, sẽ thoát. Mặt khác, giá trị của tham số được thay thế.
Bộ chỉ huy đại tá
Tôi có lẽ nên thêm rằng lệnh dấu hai chấm đơn giản là có các đối số được đánh giá và sau đó thành công. Đây là ký hiệu nhận xét shell gốc (trước ' #
' đến cuối dòng). Trong một thời gian dài, các kịch bản shell Bourne có dấu hai chấm là ký tự đầu tiên. Shell C sẽ đọc một tập lệnh và sử dụng ký tự đầu tiên để xác định xem nó dành cho C Shell ( #
băm '' hay shell Bourne ( :
dấu hai chấm '). Sau đó, hạt nhân đã tham gia vào hành động và thêm hỗ trợ cho ' #!/path/to/program
' và vỏ Bourne nhận được ' #
', và quy ước đại tràng đã diễn ra bên lề. Nhưng nếu bạn bắt gặp một kịch bản bắt đầu bằng dấu hai chấm, bây giờ bạn sẽ biết tại sao.
Vị trí của dấu ngoặc kép
Blong hỏi trong một bình luận :
Bất kỳ suy nghĩ về cuộc thảo luận này? https://github.com/koalaman/shellcheck/issues/380#issuecomment-145872749
Ý chính của cuộc thảo luận là:
Tuy nhiên, khi tôi shellcheck
(với phiên bản 0.4.1), tôi nhận được thông báo này:
In script.sh line 13:
: ${FOO:?"The environment variable 'FOO' must be set and non-empty"}
^-- SC2086: Double quote to prevent globbing and word splitting.
Bất cứ lời khuyên về những gì tôi nên làm trong trường hợp này?
Câu trả lời ngắn gọn là "làm như shellcheck
gợi ý":
: "${STATE?Need to set STATE}"
: "${DEST:?Need to set DEST non-empty}"
Để minh họa tại sao, nghiên cứu sau đây. Lưu ý rằng :
lệnh không lặp lại các đối số của nó (nhưng shell sẽ đánh giá các đối số). Chúng tôi muốn xem các đối số, vì vậy mã dưới đây sử dụng printf "%s\n"
thay cho :
.
$ mkdir junk
$ cd junk
$ > abc
$ > def
$ > ghi
$
$ x="*"
$ printf "%s\n" ${x:?You must set x} # Careless; not recommended
abc
def
ghi
$ unset x
$ printf "%s\n" ${x:?You must set x} # Careless; not recommended
bash: x: You must set x
$ printf "%s\n" "${x:?You must set x}" # Careful: should be used
bash: x: You must set x
$ x="*"
$ printf "%s\n" "${x:?You must set x}" # Careful: should be used
*
$ printf "%s\n" ${x:?"You must set x"} # Not quite careful enough
abc
def
ghi
$ x=
$ printf "%s\n" ${x:?"You must set x"} # Not quite careful enough
bash: x: You must set x
$ unset x
$ printf "%s\n" ${x:?"You must set x"} # Not quite careful enough
bash: x: You must set x
$
Lưu ý cách giá trị trong $x
được mở rộng thành đầu tiên *
và sau đó là danh sách tên tệp khi biểu thức tổng thể không nằm trong dấu ngoặc kép. Đây là những gì shellcheck
được khuyến nghị nên được sửa chữa. Tôi đã không xác minh rằng nó không phản đối biểu mẫu trong đó biểu thức được đặt trong dấu ngoặc kép, nhưng đó là một giả định hợp lý rằng nó sẽ ổn.