Tôi có thể bỏ qua các trích dẫn ở bên phải của bài tập địa phương không?
function foo {
local myvar=${bar}
stuff()
}
Tôi chủ yếu quan tâm đến bash
, nhưng bất kỳ thông tin nào về các trường hợp góc trong các vỏ khác đều được chào đón.
Tôi có thể bỏ qua các trích dẫn ở bên phải của bài tập địa phương không?
function foo {
local myvar=${bar}
stuff()
}
Tôi chủ yếu quan tâm đến bash
, nhưng bất kỳ thông tin nào về các trường hợp góc trong các vỏ khác đều được chào đón.
Câu trả lời:
Dấu ngoặc kép là cần thiết trong export foo="$var"
hoặc local foo="$var"
(hoặc readonly
, typeset
, declare
và biến tuyên bố khác lệnh ) trong:
dash
sh
của NetBSD (cũng dựa trên vỏ Almquist).sh
của FreeBSD 9.2 trở lên (xem sự thay đổi trong 9,3 )yash
zsh
với các phiên bản trước 5.1 trong ksh
hoặc sh
mô phỏng (hoặc cho export var="$(cmd)"
nơi zsh
sẽ thực hiện phân tách từ nếu không (không phải là toàn cầu)).Nếu không, việc mở rộng biến sẽ chịu sự phân tách từ và / hoặc tạo tên tệp như trong bất kỳ đối số nào đối với bất kỳ lệnh nào khác.
Và không cần thiết trong:
bash
ksh
(tất cả các triển khai)sh
của FreeBSD 9,3 hoặc mới hơnsh
(từ năm 2005)zsh
Trong zsh
, split + global không bao giờ được thực hiện khi mở rộng tham số, trừ khi trong sh
hoặc ksh
mô phỏng, nhưng tách (không phải toàn cầu) được thực hiện khi thay thế lệnh. Vì phiên bản 5.1, export
/ local
và các lệnh khai báo khác đã trở thành các lệnh từ khóa / dựng sẵn kép như trong các shell khác ở trên, điều đó có nghĩa là trích dẫn là không cần thiết, ngay cả trong sh
/ ksh
mô phỏng và thậm chí để thay thế lệnh.
Có những trường hợp đặc biệt khi trích dẫn là cần thiết ngay cả trong các shell đó như:
a="b=some value"
export "$a"
Hay nói chung hơn, nếu bất cứ điều gì còn lại của =
(bao gồm =
) được trích dẫn hoặc kết quả của một số mở rộng (như export 'foo'="$var"
, export foo\="$var"
hoặc export foo$((n+=1))="$var"
( $((...))
cũng nên được trích dẫn thực sự) ...). Hay nói cách khác, khi đối số export
sẽ không phải là một phép gán biến hợp lệ nếu được viết mà không có export
.
Nếu export
/ local
tên lệnh bản thân được trích dẫn (ngay cả trong phần như "export" a="$b"
, 'ex'port a="$b"
, \export a="$b"
, hoặc thậm chí ""export a="$b"
), các dấu ngoặc kép quanh $b
là cần thiết trừ AT & T ksh
và mksh
.
Nếu export
/ local
hoặc một phần nào đó là kết quả của một số mở rộng (như trong cmd=export; "$cmd" a="$b"
hoặc thậm chí export$(:) a="$b"
) hoặc trong những thứ như dryrun=; $dryrun export a="$b"
), thì dấu ngoặc kép là cần thiết trong mỗi vỏ.
Trong trường hợp > /dev/null export a="$b"
, các trích dẫn là cần thiết trong pdksh
và một số dẫn xuất của nó.
Đối với command export a="$b"
, các trích dẫn là cần thiết trong mọi shell nhưng mksh
và ksh93
(với cùng một cảnh báo về command
và export
không phải là kết quả của một số mở rộng).
Chúng không cần thiết trong bất kỳ shell nào khi được viết:
foo=$var export foo
(cú pháp đó cũng tương thích với trình bao Bourne nhưng trong các phiên bản gần đây của zsh
, chỉ hoạt động khi trong sh
/ ksh
mô phỏng).
(lưu ý rằng var=value local var
không nên được sử dụng vì hành vi khác nhau giữa các vỏ).
Cũng lưu ý rằng việc sử dụng export
với một bài tập cũng có nghĩa là trạng thái thoát của cmd
in export var="$(cmd)"
bị mất. Làm điều đó như export var; var=$(cmd)
không có vấn đề đó.
Cũng hãy cẩn thận với trường hợp đặc biệt này với bash
:
$ bash -c 'IFS=; export a="$*"; echo "$a"' bash a b
ab
$ bash -c 'IFS=; export a=$*; echo "$a"' bash a b
a b
Lời khuyên của tôi sẽ là luôn luôn trích dẫn.
zsh
dấu ngoặc kép là cần thiết local foo="$(cmd)"
vì từ viết (nhưng không tạo tên tệp) được thực hiện cho các thay thế lệnh không được trích dẫn (nhưng không phải cho mở rộng tham số không trích dẫn), trừ khi KSH_TYPESET
được bật, trong trường hợp đó trích dẫn không cần thiết. Có lý? Không? Sau đó, luôn luôn trích dẫn mọi thứ trừ khi bạn biết chính xác những gì bạn đang làm.
Tôi thường trích dẫn bất kỳ việc sử dụng các biến trong đó có thể có các ký tự như khoảng trắng. Nếu không, bạn sẽ gặp vấn đề như thế này:
#!/bin/bash
bar="hi bye"
function foo {
local myvar=${bar}
printf "%s\n" $myvar
printf "%s\n" "$myvar"
}
foo
Việc sử dụng biến trong một bài tập dường như không cần dấu ngoặc kép, nhưng khi bạn sử dụng nó, chẳng hạn như trong phần printf
bạn sẽ cần nó được trích dẫn ở đó:
printf "%s\n" "$myvar"
LƯU Ý: Hãy nhớ rằng biến $IFS
là thứ chi phối các ký tự phân cách.
IFS The Internal Field Separator that is used for word splitting after
expansion and to split lines into words with the read builtin command.
The default value is ``<space><tab><newline>''.
Với tính năng gỡ lỗi được kích hoạt trong Bash, chúng ta có thể thấy những gì xảy ra đằng sau hậu trường.
$ bash -x cmd.bash
+ bar='hi bye'
+ foo
+ local 'myvar=hi bye'
+ printf '%s\n' hi bye
hi
bye
+ printf '%s\n' 'hi bye'
hi bye
Ở trên chúng ta có thể thấy rằng biến số $bar
đã được xử lý tốt $myvar
nhưng sau đó khi chúng ta sử dụng, $myvar
chúng ta phải nhận thức được nội dung $myvar
khi chúng ta sử dụng nó.
bash
và ksh
trong local
/ typeset
... builtins đặc biệt).