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, declarevà biến tuyên bố khác lệnh ) trong:
dashshcủa NetBSD (cũng dựa trên vỏ Almquist).shcủa FreeBSD 9.2 trở lên (xem sự thay đổi trong 9,3 )yashzshvới các phiên bản trước 5.1 trong kshhoặc shmô phỏng (hoặc cho export var="$(cmd)"nơi zshsẽ 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:
bashksh (tất cả các triển khai)shcủa FreeBSD 9,3 hoặc mới hơnsh(từ năm 2005)zshTrong zsh, split + global không bao giờ được thực hiện khi mở rộng tham số, trừ khi trong shhoặc kshmô 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/ localvà 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/ kshmô 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ố exportsẽ 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/ localtê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 $blà cần thiết trừ AT & T kshvà mksh.
Nếu export/ localhoặ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 pdkshvà 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 mkshvà ksh93(với cùng một cảnh báo về commandvà exportkhô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/ kshmô phỏng).
(lưu ý rằng var=value local varkhô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 exportvới một bài tập cũng có nghĩa là trạng thái thoát của cmdin 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.
zshdấ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 printfbạn sẽ cần nó được trích dẫn ở đó:
printf "%s\n" "$myvar"
LƯU Ý: Hãy nhớ rằng biến $IFSlà 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 $myvarnhưng sau đó khi chúng ta sử dụng, $myvarchúng ta phải nhận thức được nội dung $myvarkhi chúng ta sử dụng nó.
bashvà kshtrong local/ typeset... builtins đặc biệt).