it-swarm-vi.com

$ VAR so với $ {VAR} và trích dẫn hay không trích dẫn

Tôi có thể viết

VAR=$VAR1
VAR=${VAR1}
VAR="$VAR1"
VAR="${VAR1}"

kết quả cuối cùng đối với tôi dường như giống nhau. Tại sao tôi nên viết cái này hay cái kia? có ai trong số này không di động/POSIX không?

150
xenoterracide

VAR=$VAR1 là phiên bản đơn giản hóa của VAR=${VAR1}. Có những thứ thứ hai có thể làm mà thứ nhất không thể, ví dụ, tham chiếu một chỉ mục mảng (không di động) hoặc loại bỏ một chuỗi con (POSIX-Portable). Xem phần Thêm về các biến trong Hướng dẫn Bash cho người mới bắt đầu và Mở rộng tham số trong thông số POSIX.

Sử dụng dấu ngoặc kép quanh một biến như trong rm -- "$VAR1" hoặc là rm -- "${VAR}" là một ý tưởng tốt. Điều này làm cho nội dung của biến là một đơn vị nguyên tử. Nếu giá trị biến chứa khoảng trống (tốt, các ký tự trong $IFS biến đặc biệt, khoảng trống theo mặc định) hoặc ký tự toàn cầu và bạn không trích dẫn nó, sau đó mỗi Word được xem xét để tạo tên tệp (globalbing) có phần mở rộng tạo ra nhiều đối số cho bất cứ điều gì bạn đang làm.

$ find .
.
./*r*
./-rf
./another
./filename
./spaced filename
./another spaced filename
./another spaced filename/x
$ var='spaced filename'
# usually, 'spaced filename' would come from the output of some command and you weren't expecting it
$ rm $var
rm: cannot remove 'spaced': No such file or directory
# oops! I just ran 'rm spaced filename'
$ var='*r*'
$ rm $var
# expands to: 'rm' '-rf' '*r*' 'another spaced filename'

$ find .
.
./another
./spaced filename
./another spaced filename
$ var='another spaced filename'
$ rm -- "$var"
$ find .
.
./another
./spaced filename

Về tính di động: Theo POSIX.1-2008 phần 2.6.2 , dấu ngoặc nhọn là tùy chọn.

108
Shawn J. Goff

${VAR}$VAR hoàn toàn tương đương. Đối với mở rộng biến đơn giản, lý do duy nhất để sử dụng ${VAR} là khi phân tích cú pháp sẽ lấy quá nhiều ký tự vào tên biến, như trong ${VAR1}_$VAR2 (không có niềng răng sẽ tương đương với ${VAR1_}$VAR2). Mở rộng trang trí nhất (${VAR:=default}, ${VAR#prefix}, Tầm) yêu cầu niềng răng.

Trong một phép gán biến, tách trường (tức là tách ở khoảng trắng trong giá trị) và mở rộng tên đường dẫn (tức là toàn cầu hóa) bị tắt, vì vậy VAR=$VAR1 hoàn toàn tương đương với VAR="$VAR1", trong tất cả các vỏ POSIX và trong tất cả các sh-POSIX trước mà tôi đã nghe nói. (Tham chiếu POSIX: các lệnh đơn giản ). Cho cùng một lý do, VAR=* đáng tin cậy đặt VAR thành chuỗi ký tự *; tất nhiên VAR=a b đặt VAR thành ab là một từ riêng biệt ở vị trí đầu tiên. Nói chung, dấu ngoặc kép là không cần thiết trong đó cú pháp Shell mong đợi một từ duy nhất, ví dụ trong case … in (nhưng không phải trong mẫu), nhưng ngay cả ở đó bạn cũng cần cẩn thận: ví dụ POSIX chỉ định rằng mục tiêu chuyển hướng (>$filename) không yêu cầu trích dẫn trong tập lệnh, nhưng một số shell bao gồm bash yêu cầu dấu ngoặc kép ngay cả trong tập lệnh. Xem Khi nào cần trích dẫn kép? để phân tích kỹ hơn.

Bạn cần có dấu ngoặc kép trong các trường hợp khác, đặc biệt là trong export VAR="${VAR1}" (có thể được viết tương đương export "VAR=${VAR1}") trong nhiều shell (POSIX để mở trường hợp này). Sự giống nhau của trường hợp này với các bài tập đơn giản và tính chất phân tán của danh sách các trường hợp bạn không cần dấu ngoặc kép, là lý do tại sao tôi khuyên bạn chỉ nên sử dụng dấu ngoặc kép trừ khi bạn muốn tách và toàn cầu.

65

Bảng báo giá

Hãy xem xét rằng trích dẫn kép được sử dụng để mở rộng biến đổi và trích dẫn đơn được sử dụng để trích dẫn mạnh, tức là, mở rộng sans.

Sự bành trướng:

this='foo'
that='bar'
these="$this"
those='$that'

Đầu ra:

for item in "$this" "$that" "$these" "$those"; do echo "$item"; done
foo
bar
foo
$that

Có thể đáng để đề cập rằng bạn nên sử dụng trích dẫn bất cứ khi nào có thể vì một số lý do, trong số đó tốt nhất được coi là thực hành tốt nhất và dễ đọc. Ngoài ra bởi vì Bash đôi khi kỳ quặc và thường cho những cách dường như phi logic hoặc không hợp lý/bất ngờ, và thay đổi trích dẫn ngầm định những kỳ vọng thành rõ ràng, làm giảm bề mặt lỗi đó (hoặc tiềm năng - cho nó).

Và mặc dù nó hoàn toàn hợp pháp đối với không quote, và sẽ hoạt động trong hầu hết các trường hợp, chức năng đó được cung cấp để thuận tiện và có lẽ ít di động hơn. thực hành chính thức đầy đủ được đảm bảo để phản ánh ý định và kỳ vọng là trích dẫn.

Thay thế

Bây giờ cũng xem xét rằng cấu trúc "${somevar}" được sử dụng cho các hoạt động thay thế. Một số trường hợp sử dụng, chẳng hạn như thay thế và mảng.

Thay thế (tước):

thisfile='foobar.txt.bak'
foo="${thisfile%.*}"   # removes shortest part of value in $thisfile matching after '%' from righthand side
bar="${thisfile%%.*}"  # removes longest matching

for item in "$foo" "$bar"; do echo "$item"; done
foobar.txt
foobar

Thay thế (thay thế):

foobar='Simplest, least effective, least powerful'
# ${var/find/replace_with}
foo="${foobar/least/most}"   #single occurrence
bar="${foobar//least/most}"  #global occurrence (all)

for item in "$foobar" "$foo" "$bar"; do echo "$item"; done
Simplest, least effective, least powerful
Simplest, most effective, least powerful
Simplest, most effective, most powerful

Mảng:

mkdir temp
# create files foo.txt, bar.txt, foobar.txt in temp folder
touch temp/{foo,bar,foobar}.txt
# alpha is array of output from ls  
alpha=($(ls temp/*))

echo "$alpha"         #  temp/foo.txt
echo "${alpha}"       #  temp/foo.txt
echo "${alpha[@]}"    #  temp/bar.txt  temp/foobar.txt  temp/foo.txt
echo "${#alpha}"      #  12 # length of first element (implicit index [0])
echo "${#alpha[@]}"   #  3  # number of elements
echo "${alpha[1]}"    #  temp/foobar.txt # second element
echo "${#alpha[1])"   #  15 # length of second element

for item in "${alpha[@]}"; do echo "$item"; done
temp/bar.txt
temp/foobar.txt
temp/foo.txt

Tất cả điều này hầu như không làm trầy xước bề mặt của "${var}" cấu trúc thay thế. Tham chiếu dứt khoát cho kịch bản Bash Shell là tài liệu tham khảo trực tuyến miễn phí, TLDP Dự án Tài liệu Linux https://www.tldp.org/LDP/abs/html/parameter-substitution.html

9
SYANiDE
ls -la

lrwxrwxrwx.  1 root root      31 Nov 17 13:13 prodhostname
lrwxrwxrwx.  1 root root      33 Nov 17 13:13 testhostname
lrwxrwxrwx.  1 root root      32 Nov 17 13:13 justname

kết thúc sau đó:

env=$1
    if [ ! -f /dirname/${env}hostname ]

đáng nói đến như một ví dụ rõ ràng hơn về việc sử dụng curlies

0
ninjabber