JAWABAN SINGKAT
Seperti yang dikatakan orang lain - Anda harus selalu mengutip variabel untuk mencegah perilaku aneh. Jadi gunakan echo "$ foo" sebagai ganti hanya echo $ foo .
JAWABAN PANJANG
Saya pikir contoh ini memerlukan penjelasan lebih lanjut karena ada lebih banyak hal yang terjadi daripada yang terlihat di awal.
Saya dapat melihat di mana kebingungan Anda datang karena setelah Anda menjalankan contoh pertama Anda, Anda mungkin berpikir sendiri bahwa shell jelas melakukan:
- Perluasan parameter
- Perluasan nama file
Jadi dari contoh pertama Anda:
me$ FOO="BAR * BAR"
me$ echo $FOO
Setelah ekspansi parameter setara dengan:
me$ echo BAR * BAR
Dan setelah perluasan nama file sama dengan:
me$ echo BAR file1 file2 file3 file4 BAR
Dan jika Anda mengetik echo BAR * BAR
di baris perintah, Anda akan melihat bahwa keduanya setara.
Jadi Anda mungkin berpikir "jika saya lolos dari *, saya dapat mencegah perluasan nama file"
Jadi dari contoh kedua Anda:
me$ FOO="BAR \* BAR"
me$ echo $FOO
Setelah perluasan parameter harus setara dengan:
me$ echo BAR \* BAR
Dan setelah perluasan nama file harus sama dengan:
me$ echo BAR \* BAR
Dan jika Anda mencoba mengetik "echo BAR \ * BAR" secara langsung ke baris perintah, ia memang akan mencetak "BAR * BAR" karena perluasan nama file dicegah oleh escape.
Jadi mengapa menggunakan $ foo tidak berhasil?
Itu karena ada ekspansi ketiga yang terjadi - Penghapusan Kutipan. Dari penghapusan kutipan manual bash adalah:
Setelah perluasan sebelumnya, semua kemunculan karakter '\', '' ', dan' "'yang bukan hasil dari salah satu perluasan di atas akan dihapus.
Jadi yang terjadi adalah saat Anda mengetik perintah langsung ke baris perintah, karakter escape bukan hasil ekspansi sebelumnya sehingga BASH menghapusnya sebelum mengirimnya ke perintah echo, tetapi pada contoh kedua, "\ *" adalah hasil dari perluasan Parameter sebelumnya, jadi TIDAK dihapus. Akibatnya, echo menerima "\ *" dan itulah yang dicetaknya.
Perhatikan perbedaan antara contoh pertama - "*" tidak disertakan dalam karakter yang akan dihapus oleh Penghapusan Kutipan.
Saya harap ini masuk akal. Pada akhirnya kesimpulannya sama - gunakan saja tanda kutip. Saya hanya berpikir saya akan menjelaskan mengapa melarikan diri, yang secara logis seharusnya berfungsi jika hanya ekspansi Parameter dan Nama file yang berperan, tidak berfungsi.
Untuk penjelasan lengkap tentang ekspansi BASH, lihat:
http://www.gnu.org/software/bash/manual/bashref.html#Shell-Expansions