Pertanyaan ini bukan tentang bagaimana menulis string literal yang benar. Saya tidak dapat menemukan pertanyaan terkait yang bukan tentang cara keluar dari variabel untuk konsumsi langsung dalam skrip atau oleh program lain.
Tujuan saya adalah mengaktifkan skrip untuk menghasilkan skrip lain. Ini karena tugas dalam skrip yang dihasilkan akan berjalan di mana saja dari 0 hingga n kali di komputer lain, dan data yang darinya dihasilkan dapat berubah sebelum dijalankan (lagi), jadi melakukan operasi secara langsung, melalui jaringan akan tidak bekerja.
Diberikan variabel yang diketahui yang mungkin berisi karakter khusus seperti tanda kutip tunggal, saya perlu menuliskannya sebagai string literal yang sepenuhnya diloloskan, misalnya variabel yang foo
mengandung bar'baz
harus muncul dalam skrip yang dihasilkan sebagai:
qux='bar'\''baz'
yang akan ditulis dengan menambahkan "qux=$foo_esc"
ke baris script lainnya. Saya melakukannya menggunakan Perl seperti ini:
foo_esc="'`perl -pe 's/('\'')/\\1\\\\\\1\\1/g' <<<"$foo"`'"
tapi ini sepertinya berlebihan.
Saya tidak berhasil melakukannya dengan bash sendirian. Saya telah mencoba banyak variasi:
foo_esc="'${file//\'/\'\\\'\'}'"
foo_esc="'${file//\'/'\\''}'"
tetapi salah satu garis miring muncul di output (ketika saya lakukan echo "$foo"
), atau mereka menyebabkan kesalahan sintaks (mengharapkan input lebih lanjut jika dilakukan dari shell).
alias
dan / atauset
secara universalalias "varname=$varname" varname
atauvar=value set
Jawaban:
Bash memiliki opsi ekspansi parameter untuk kasus ini :
Jadi dalam hal ini:
Ini didukung di Bash 4.4 dan lebih tinggi. Ada beberapa opsi untuk bentuk ekspansi lain juga, dan untuk secara khusus menghasilkan pernyataan penugasan lengkap (
@A
).sumber
bad substitution
."${foo:q}"
."${foo@Q}"
bekerja!Bash menyediakan
printf
penentu%q
format bawaan, yang menjalankan shell untuk Anda, bahkan di versi Bash yang lebih lama (<4.0):Trik ini juga dapat digunakan untuk mengembalikan array data dari suatu fungsi:
Perhatikan bahwa Bash
printf
builtin berbeda dariprintf
utilitas yang dibundel dengan sebagian besar sistem operasi mirip Unix. Jika, karena alasan tertentu,printf
perintah memanggil utilitas alih-alih builtin, Anda selalu dapat menjalankannyabuiltin printf
.sumber
'Ne'\''er do well'
, dll., Yaitu kutipan yang termasuk dalam output.[[ 'Ne'\''er do well' == Ne\'er\ do\ well ]] && echo 'equivalent!'
will echoequivalent!
'hello'
menghasilkan nilai yang salah''\''hello''
, yang memiliki string kosong terkemuka yang tidak perlu (dua tanda kutip tunggal pertama), dan tanda kutip tunggal trailing yang tidak tepat.$'escape-these-chars'
adalah fitur mengutip ANSI-C dari Bash yang menyebabkan semua karakter dalam string yang ditentukan untuk melarikan diri. Dengan demikian, untuk dengan mudah membuat string literal yang berisi baris baru di dalam nama file (misalnya$'first-line\nsecond-line')
, gunakan\n
dalam konstruk ini.Saya kira saya tidak RTFM. Itu bisa dilakukan seperti ini:
Lalu
echo "$foo_esc"
berikan yang diharapkan'bar'\''baz'
Bagaimana saya sebenarnya menggunakannya dengan fungsi:
Mengubah ini untuk menggunakan
printf
built-in dari solusi Dejay:sumber
Ada beberapa solusi untuk mengutip nilai var:
alias
Dalam kebanyakan shells (di mana alias tersedia) (kecuali csh, tcsh dan mungkin yang lain suka csh):
Ya, ini bekerja di banyak
sh
cangkang seperti dasbor atau abu.atur
Juga di sebagian besar shell (sekali lagi, bukan csh):
mengeset
dalam beberapa shell (setidaknya ksh, bash dan zsh):
ekspor
Pertama lakukan:
Kemudian gunakan:
ksh
export -p | grep 'qux='
bashexport -p | grep 'qux='
zsh
export -p qux
kutipan
bash
echo "${qux@Q}"
zsh
echo "${(qq)qux}"
# dari satu hingga empat q dapat digunakan.sumber
grep
denganexport
atauset
bisa pecah pada variabel yang berisi baris tertanam.