Saya bisa menulis
VAR=$VAR1
VAR=${VAR1}
VAR="$VAR1"
VAR="${VAR1}"
hasil akhirnya bagi saya semua tampak hampir sama. Mengapa saya harus menulis yang satu atau yang lain? apakah semua ini tidak portabel / POSIX?
Saya bisa menulis
VAR=$VAR1
VAR=${VAR1}
VAR="$VAR1"
VAR="${VAR1}"
hasil akhirnya bagi saya semua tampak hampir sama. Mengapa saya harus menulis yang satu atau yang lain? apakah semua ini tidak portabel / POSIX?
Jawaban:
VAR=$VAR1
adalah versi sederhana dari VAR=${VAR1}
. Ada hal-hal yang kedua dapat lakukan yang pertama tidak bisa, misalnya referensi indeks array (tidak portabel) atau menghapus substring (POSIX-portable). Lihat bagian Lebih lanjut tentang variabel pada Panduan Bash untuk Pemula dan Ekspansi Parameter dalam spesifikasi POSIX.
Menggunakan tanda kutip di sekitar variabel sebagai rm -- "$VAR1"
atau rm -- "${VAR}"
adalah ide yang baik. Ini menjadikan isi variabel sebagai unit atom. Jika nilai variabel berisi kosong (well, karakter dalam $IFS
variabel khusus, kosong secara default) atau karakter globbing dan Anda tidak mengutipnya, maka setiap kata dipertimbangkan untuk pembuatan nama file (globbing) yang perluasannya membuat banyak argumen untuk apa pun yang Anda sedang dilakukan.
$ 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
Pada portabilitas: Menurut POSIX.1-2008 bagian 2.6.2 , kurung kurawal adalah opsional.
var1=$var
ekspansi memberikan kesalahan?
export VAR=$VAR1
. Sedangkan untuk kawat gigi, mereka adalah opsional (periksa paragraf keempat dari bagian yang Anda kutip; ini adalah kasus di semua shell pra-POSIX dan POSIX).
${VAR}
dan $VAR
persis sama. Untuk ekspansi variabel biasa, satu-satunya alasan untuk digunakan ${VAR}
adalah ketika penguraian sebaliknya akan mengambil terlalu banyak karakter ke dalam nama variabel, seperti dalam ${VAR1}_$VAR2
(yang tanpa kawat gigi akan setara dengan ${VAR1_}$VAR2
). Ekspansi yang paling menghiasi ( ${VAR:=default}
, ${VAR#prefix}
, ...) membutuhkan kawat gigi.
Dalam penugasan variabel, pemisahan bidang (mis. Pemisahan pada spasi putih pada nilai) dan perluasan pathname (yaitu penggumpalan) dimatikan, jadi VAR=$VAR1
persis sama dengan VAR="$VAR1"
, di semua shell POSIX dan di semua sh pre-POSIX yang pernah saya dengar . (POSIX ref: perintah sederhana ). Untuk alasan yang sama, VAR=*
andal disetel VAR
ke string literal *
; tentu saja VAR=a b
diatur VAR
ke a
karena kata b
itu terpisah di tempat pertama. Secara umum, tanda kutip ganda tidak diperlukan di mana sintaks shell mengharapkan satu kata, misalnya dalamcase … in
(tetapi tidak dalam pola), tetapi bahkan di sana Anda harus berhati-hati: misalnya POSIX menentukan bahwatarget pengalihan ( >$filename
) tidak memerlukan kuotasi dalam skrip, tetapi beberapa shell termasuk bash memang membutuhkan kuotasi ganda bahkan dalam skrip. Lihat Kapan perlu kutip ganda? untuk analisis yang lebih menyeluruh.
Anda memang membutuhkan tanda kutip ganda dalam kasus lain, khususnya dalam export VAR="${VAR1}"
(yang dapat dituliskan secara setara export "VAR=${VAR1}"
) dalam banyak shell (POSIX membiarkan case ini terbuka). Kesamaan kasus ini dengan penugasan sederhana, dan sifat daftar kasus yang tersebar di mana Anda tidak memerlukan tanda kutip ganda, itulah sebabnya saya sarankan hanya menggunakan tanda kutip ganda kecuali jika Anda ingin membagi dan menggumpal.
IFS
karakter apa pun karena saya ingin terbiasa. Satu pengecualian adalah saya tidak mengutip nilai ketika melakukan penugasan variabel (kecuali diperlukan, seperti ketika nilai mengandung spasi). Ini membuat penyorotan sintaksis editor lebih berguna ketika ada substitusi perintah seperti FOO=$(BAR=$(BAZ=blah; printf %s "${BAZ}"); printf %s "${BAR}")
. Alih-alih mewarnai semua warna "string", saya mendapatkan highlight sintaks dari kode bersarang. Ini juga sebabnya saya menghindari backticks.
>$file
OK di skrip POSIX, itu tidak di bash bahkan ketika non-interaktif (kecuali kepatuhan POSIX diberlakukan dengan $POSIXLY_CORRECT
atau --posix
...).
VAR=$VAR1
, kadang-kadang saya terkejut olehnya local VAR=$VAR1
, yang saya ingat bekerja secara berbeda dalam beberapa hal, setidaknya dalam beberapa hal. Tapi atm, saya tidak bisa mereproduksi perbedaan.
local VAR=$VAR1
seperti export VAR=$VAR1
, itu tergantung pada shell.
Pertimbangkan bahwa kutipan ganda digunakan untuk ekspansi variabel, dan kutipan tunggal digunakan untuk penawaran kuat, yaitu, ekspansi sans.
this='foo'
that='bar'
these="$this"
those='$that'
for item in "$this" "$that" "$these" "$those"; do echo "$item"; done
foo
bar
foo
$that
Mungkin bermanfaat untuk menyebutkan bahwa Anda harus menggunakan kutipan sedapat mungkin karena beberapa alasan, di antaranya adalah yang dianggap praktik terbaik, dan untuk keterbacaan. Juga karena Bash kadang-kadang unik dan sering untuk cara yang tampaknya tidak logis atau tidak masuk akal / tidak terduga, dan kutipan mengubah ekspektasi implisit ke eksplisit, yang mengurangi permukaan kesalahan (atau potensi-untuknya).
Dan meskipun sepenuhnya legal untuk tidak mengutip, dan akan berfungsi dalam banyak kasus, fungsionalitas itu disediakan untuk kenyamanan dan mungkin lebih mudah dibawa-bawa. praktik formal sepenuhnya dijamin untuk mencerminkan niat dan harapan adalah mengutip.
Sekarang perhatikan juga bahwa konstruk "${somevar}"
tersebut digunakan untuk operasi substitusi. Beberapa kasus penggunaan, seperti penggantian, dan array.
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
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
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
Semua ini nyaris tidak menggores permukaan "${var}"
konstruksi substitusi. Referensi definitif untuk skrip Bash shell adalah referensi online gratis, TLDP The Linux Documentation Projecthttps://www.tldp.org/LDP/abs/html/parameter-substitution.html
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
akhir saja:
env=$1
if [ ! -f /dirname/${env}hostname ]
layak disebut sebagai contoh yang lebih jelas tentang penggunaan ikal