Variabel yang tidak dikutip (seperti dalam $var
) atau substitusi perintah (seperti dalam $(cmd)
atau `cmd`
) adalah operator split + glob dalam shell yang mirip Bourne.
Artinya, konten mereka dibagi sesuai dengan nilai saat ini dari $IFS
variabel khusus (yang secara default berisi spasi, tab, dan karakter baris baru)
Dan kemudian setiap kata yang dihasilkan dari pemisahan itu tunduk pada generasi nama file (juga dikenal sebagai globbing atau ekspansi nama file ), yaitu, mereka dianggap sebagai pola dan diperluas ke daftar file yang cocok dengan pola itu.
Jadi for i in $(xrandr)
, dalam $(xrandr)
, karena tidak ada dalam tanda kutip, dibagi pada urutan spasi, tab, dan karakter baris baru. Dan setiap kata yang dihasilkan dari pemisahan tersebut diperiksa untuk mencocokkan nama file (atau dibiarkan seolah-olah tidak cocok dengan file apa pun), dan for
mengulanginya semua.
Dalam for i in "$(xrandr)"
, kami tidak menggunakan operator split + glob seperti yang dikutip oleh substitusi , jadi ada satu pass dalam loop pada satu nilai: output dari xrandr
(tanpa karakter baris tambahan yang memerintahkan strip pengganti ).
Namun dalam echo $i
, $i
tidak dikutip lagi, sehingga konten $i
split dan tunduk pada generasi nama file dan mereka dilewatkan sebagai argumen terpisah untuk echo
perintah (dan echo
output argumennya dipisahkan oleh spasi).
Jadi pelajaran yang didapat:
- jika Anda tidak ingin pemisahan kata atau pembuatan nama file , selalu kutip ekspansi variabel dan penggantian perintah
- jika Anda memang ingin pemisahan kata atau pembuatan nama file , biarkan tidak dikutip tetapi tetapkan
$IFS
sesuai dan / atau aktifkan atau nonaktifkan pembuatan nama file jika diperlukan ( set -f
, set +f
).
Biasanya, dalam contoh Anda di atas, jika Anda ingin mengulang daftar kata-kata yang dipisahkan kosong di output dari xrandr
, Anda harus:
- biarkan
$IFS
pada nilai default-nya (atau tidak disetel) untuk dibagi menjadi kosong
- Gunakan
set -f
untuk menonaktifkan generasi nama file kecuali Anda yakin bahwa xrandr
tidak pernah output setiap *
atau ?
atau [
karakter (yang wildcard digunakan dalam pola generasi nama file)
Dan kemudian hanya menggunakan operator split + glob (hanya biarkan substitusi perintah atau ekspansi variabel tidak dikutip) di in
bagian for
loop:
set -f; unset -v IFS
for i in $(xrandr); do whatever with "$i"; done
Jika Anda ingin loop atas (non-kosong) baris dari xrandr
output, Anda akan perlu untuk set $IFS
untuk karakter baris baru:
IFS='
'