Saya memiliki skrip wrapper yang berfungsi dan kemudian meneruskan parameter asli ke alat lain:
#!/bin/bash
# ...
other_tool -a -b "$@"
Ini berfungsi dengan baik, kecuali "alat lain" dijalankan dalam subkulit:
#!/bin/bash
# ...
bash -c "other_tool -a -b $@"
Jika saya memanggil skrip pembungkus saya seperti ini:
wrapper.sh -x "blah blup"
kemudian, hanya argumen asli pertama (-x) yang diserahkan ke "other_tool". Pada kenyataannya, saya tidak membuat subkulit, tetapi meneruskan argumen asli ke shell di ponsel Android, yang seharusnya tidak membuat perbedaan:
#!/bin/bash
# ...
adb sh -c "other_tool -a -b $@"
Tidak ada solusi yang berfungsi dengan baik. Lewati saja x / \ \ "b \" / aaaaa / \ 'xxx \ yyyy \' / zz \ "offf \" sebagai parameter dan gagal.
Ini adalah pembungkus sederhana yang menangani setiap kasing. Catat bagaimana ia lolos dari setiap argumen dua kali.
sumber
Ubah
$@
ke$*
. Saya melakukan tes lokal kecil dan berfungsi dalam kasus saya.Menyimpan sebagai
test.sh
dan membuatnya dapat dijalankan memberiAda perbedaan halus antara
$*
dan$@
, seperti yang Anda lihat. Lihat misalnya http://ss64.com/bash/syntax-parameters.htmlUntuk pertanyaan tindak lanjut dalam komentar: Anda perlu melarikan diri mis. Spasi putih "dua kali" untuk meneruskan string dengan pemisah sebagai argumen gabungan, misalnya dengan
test.sh
dimodifikasi menjadiwc
pembungkus:Ini bekerja:
tapi:
sumber
wrapper.sh -x "blah blup"
maka subkulit tersebut mendapatkan TIGA parameter (-x, bla, blup) alih-alih DUA (-x, "bla blup")"Blah\ blup"
. Cobalah dan lihat apakah itu berhasil.Gagal karena Anda memaksa array (parameter posisi) menjadi string.
"$@"
ajaib karena memberi Anda setiap parameter terpisah sebagai string yang dikutip dengan benar. Menambahkan teks tambahan mematahkan keajaiban:"blah $@"
hanya sebuah string tunggal.Ini bisa membuat Anda lebih dekat:
Tentu saja, parameter apa pun yang berisi kutipan tunggal akan menyebabkan masalah.
sumber
Ok, penjelasan lebih lanjut:
sumber
Saya mencoba berbagai solusi, sumber yang bagus termasuk informasi latar belakang dan alternatifnya adalah misalnya BashFAQ / 096 di Greg's (alias. GreyCat's) Wiki . Secara keseluruhan saya menemukan dua berikut ini yang paling mudah dibaca (dari yang berfungsi):
Karena Bash 4.4 (sejauh yang saya tahu dari BERITA ) adalah mungkin untuk menggunakan ekspansi parameter
@Q
seperti ini:Perhatikan bahwa saya menggunakan di
$*
sini bukan$@
karena Anda ingin"other_tool -a -b ${*@Q}"
menjadi satu string tunggal, bukan satu string per argumen yang diteruskan.Jika Anda ingin melakukan hal yang sama dengan variabel array bash Anda akan memerlukan sintaks
${ARRAY[*]@Q}
(dalam tanda kutip).Jika Anda tidak memiliki Bash 4.4 atau yang lebih baru atau tidak yakin, ini adalah solusi pilihan saya:
Perhatikan bahwa di sini Anda perlu menggunakan
"$@"
alih-alih$@
atau"$*"
atau$*
karena Anda tidak ingin pemisahan kata dalam argumen, sehingga varian tanpa kutip tidak dapat digunakan, dan Anda ingin jumlah argumen dipertahankan, jadi"$*"
tidak dapat digunakan karena akan bergabung semua argumen menjadi string tunggal. Fungsi kemudian mengembalikan semua argumen dalam satu string.Jika Anda tidak peduli dengan ruang tambahan di depan argumen pertama, Anda dapat mengubah
printf
string format ke" %q"
dan menghapusseparator
variabel. Atau Anda dapat menggunakan one-liner dari jawaban Gordon Davissons .Solusi ini bekerja dengan semua kasus yang bisa saya buat, terutama:
escapeBashArgs
→ tidak adaescapeBashArgs "" ""
→'' ''
escapeBashArgs " " " "
→' ' ' '
atau\ \ \ \ \
( ruang terakhir dimakan oleh renderer situs ini )escapeBashArgs "a b" c\ d "arg with newline"
→'a b' 'c d' $'arg with\nnewline'
ataua\ \ \ \ \ \ b c\ d $'arg with\nnewline'
( baris baru antarawith
dannewline
, pada posisi lain karena pembungkus baris di situs ini )escapeBashArgs '$"'\''({:})'
→'$"'\''({:})'
atau\$\"\'\(\{:\}\)
escapeBashArgs x/\ \ \"b\"/aaaaa/\'xxx\ yyyy\'/zz\"offf\"
→'x/ "b"/aaaaa/'\''xxx yyyy'\''/zz"offf"'
ataux/\ \ \"b\"/aaaaa/\'xxx\ yyyy\'/zz\"offf\"
(Diuji dengan GNU bash 5.0.3 (1) -release.)
sumber
sumber