Sebagai contoh:
me$ FOO="BAR * BAR"
me$ echo $FOO
BAR file1 file2 file3 file4 BAR
dan menggunakan \
karakter escape:
me$ FOO="BAR \* BAR"
me$ echo $FOO
BAR \* BAR
Saya jelas melakukan sesuatu yang bodoh.
Bagaimana cara mendapatkan hasilnya BAR * BAR
?
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:
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:
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
sumber
Saya akan menambahkan sedikit ke utas lama ini.
Biasanya Anda akan menggunakan
$ echo "$FOO"
Namun, saya mengalami masalah bahkan dengan sintaks ini. Simak script berikut ini.
#!/bin/bash curl_opts="-s --noproxy * -O" curl $curl_opts "$1"
The
*
kebutuhan untuk diteruskan verbatim untukcurl
, tetapi masalah yang sama akan timbul. Contoh di atas tidak akan berfungsi (ini akan diperluas ke nama file di direktori saat ini) dan begitu pula sebaliknya\*
. Anda juga tidak dapat mengutip$curl_opts
karena akan dikenali sebagai satu opsi (tidak valid) untukcurl
.curl: option -s --noproxy * -O: is unknown curl: try 'curl --help' or 'curl --manual' for more information
Oleh karena itu saya akan merekomendasikan penggunaan
bash
variabel$GLOBIGNORE
untuk mencegah perluasan nama file sama sekali jika diterapkan ke pola global, atau gunakanset -f
bendera bawaan.#!/bin/bash GLOBIGNORE="*" curl_opts="-s --noproxy * -O" curl $curl_opts "$1" ## no filename expansion
Menerapkan contoh asli Anda:
me$ FOO="BAR * BAR" me$ echo $FOO BAR file1 file2 file3 file4 BAR me$ set -f me$ echo $FOO BAR * BAR me$ set +f me$ GLOBIGNORE=* me$ echo $FOO BAR * BAR
sumber
SELECT * FROM etc.
, ini adalah satu-satunya cara yang berhasil.FOO='BAR * BAR' echo "$FOO"
sumber
echo "$FOO"
sumber
Mungkin ada baiknya membiasakan diri menggunakan
printf
daripada menggunakanecho
baris perintah.Dalam contoh ini tidak memberikan banyak manfaat tetapi bisa lebih bermanfaat dengan keluaran yang lebih kompleks.
FOO="BAR * BAR" printf %s "$FOO"
sumber