Saya ingin menjalankan perintah dari skrip bash yang memiliki tanda kutip tunggal dan beberapa perintah lain di dalam tanda kutip tunggal dan variabel.
misalnya repo forall -c '....$variable'
Dalam format ini, $
lolos dan variabel tidak diperluas.
Saya mencoba variasi berikut tetapi ditolak:
repo forall -c '...."$variable" '
repo forall -c " '....$variable' "
" repo forall -c '....$variable' "
repo forall -c "'" ....$variable "'"
Jika saya mengganti nilai di tempat variabel perintah dieksekusi dengan baik.
Tolong beritahu saya di mana saya salah.
repo forall -c ' ...before... '"$variable"' ...after...'
bash
makan tanda kutip tunggal. Entah Anda tidak masukbash
, atau tanda kutip tunggal bukan bagian darirepo
perintah.Jawaban:
Di dalam kutipan tunggal semuanya dilestarikan secara harfiah, tanpa kecuali.
Itu berarti Anda harus menutup tanda kutip, memasukkan sesuatu, dan kemudian memasukkan kembali.
Penggabungan kata hanya dilakukan dengan penjajaran. Seperti yang dapat Anda verifikasi, setiap baris di atas adalah satu kata untuk shell. Kutipan (kutipan tunggal atau ganda, tergantung situasi) tidak mengisolasi kata-kata. Mereka hanya digunakan untuk menonaktifkan interpretasi berbagai karakter khusus, seperti spasi,
$
,,;
... Untuk tutorial yang baik tentang kutipan, lihat jawaban Mark Reed. Juga relevan: Karakter mana yang harus dihindari dalam bash?Jangan menyatukan string yang ditafsirkan oleh shell
Anda harus benar-benar menghindari membuat perintah shell dengan menggabungkan variabel. Ini adalah ide buruk yang mirip dengan rangkaian fragmen SQL (injeksi SQL!).
Biasanya dimungkinkan untuk memiliki placeholder dalam perintah, dan untuk memasok perintah bersama dengan variabel sehingga callee dapat menerimanya dari daftar argumen doa.
Misalnya, berikut ini sangat tidak aman. JANGAN LAKUKAN INI
Jika konten
$myvar
tidak dipercaya, berikut ini adalah exploit:Alih-alih doa di atas, gunakan argumen posisi. Doa berikut lebih baik - tidak bisa dieksploitasi:
Catat penggunaan kutu tunggal dalam penugasan
script
, yang artinya diambil secara harfiah, tanpa ekspansi variabel atau bentuk interpretasi lainnya.sumber
"some"thing' like'this
adalah satu kata untuk shell. Tanda kutip tidak menghentikan apa pun sejauh menyangkut penguraian, dan tidak ada cara bagi perintah yang dipanggil oleh shell untuk memberi tahu apa yang dikutip bagaimana caranya.The
repo
perintah tidak bisa peduli apa jenis kutipan mendapat. Jika Anda membutuhkan ekspansi parameter, gunakan tanda kutip ganda. Jika itu berarti Anda akhirnya harus melakukan backslash banyak hal, gunakan tanda kutip tunggal untuk sebagian besar, dan kemudian keluar dari mereka dan pergi ke ganda untuk bagian di mana Anda perlu ekspansi terjadi.Penjelasan berikut, jika Anda tertarik.
Saat Anda menjalankan perintah dari shell, perintah yang diterima sebagai argumen adalah array dari string yang diakhiri dengan null. String-string itu mungkin benar - benar mengandung karakter bukan nol.
Tetapi ketika shell sedang membangun array string dari baris perintah, itu menafsirkan beberapa karakter khusus; ini dirancang untuk membuat perintah lebih mudah (memang, mungkin) untuk diketik. Misalnya, spasi biasanya menunjukkan batas antara string dalam array; untuk alasan itu, argumen individu kadang-kadang disebut "kata-kata". Namun suatu argumen mungkin memiliki ruang di dalamnya; Anda hanya perlu beberapa cara untuk memberi tahu shell itu yang Anda inginkan.
Anda dapat menggunakan garis miring terbalik di depan karakter apa pun (termasuk spasi, atau garis miring terbalik lainnya) untuk memberi tahu shell untuk memperlakukan karakter tersebut secara harfiah. Tetapi sementara Anda dapat melakukan sesuatu seperti ini:
echo \"Thank\ you.\ \ That\'ll\ be\ \$4.96,\ please,\"\ said\ the\ cashier
... itu bisa melelahkan. Jadi cangkang menawarkan alternatif: tanda kutip. Ini datang dalam dua varietas utama.
Tanda kutip ganda disebut "kutipan pengelompokan". Mereka mencegah wildcard dan alias diperluas, tetapi sebagian besar mereka untuk memasukkan spasi dalam kata. Hal-hal lain seperti perluasan parameter dan perintah (hal-hal yang ditandai oleh a
$
) masih terjadi. Dan tentu saja jika Anda ingin tanda kutip ganda di dalam tanda kutip ganda, Anda harus melakukan backslash:echo "\"Thank you. That'll be \$4.96, please,\" said the cashier"
Tanda kutip tunggal lebih kejam. Segala sesuatu di antara mereka diambil sepenuhnya secara harfiah, termasuk garis miring terbalik. Sama sekali tidak ada cara untuk mendapatkan kutipan tunggal literal di dalam kutipan tunggal.
Untungnya, tanda kutip di shell bukan pembatas kata ; sendiri, mereka tidak mengakhiri sepatah kata pun. Anda bisa masuk dan keluar dari kutipan, termasuk antara berbagai jenis kutipan, dalam kata yang sama untuk mendapatkan hasil yang diinginkan:
echo '"Thank you. That'\''ll be $4.96, please," said the cashier'
Jadi itu lebih mudah - backslash jauh lebih sedikit, meskipun urutan kutipan-tertutup, backslashed-literal-kutipan-tunggal, buka-kutipan-tunggal memerlukan waktu untuk membiasakan diri.
Kerang modern telah menambahkan gaya kutipan lain yang tidak ditentukan oleh standar POSIX, di mana tanda kutip tunggal yang diawali diawali dengan tanda dolar. String yang dikutip mengikuti konvensi serupa ke string literal dalam bahasa pemrograman ANSI C, dan karena itu kadang-kadang disebut "string ANSI" dan
$'
...'
pasangan "kutipan ANSI". Dalam string seperti itu, saran di atas tentang backslash yang diambil secara harfiah tidak lagi berlaku. Sebaliknya, mereka menjadi istimewa lagi - Anda tidak hanya dapat menyertakan tanda kutip tunggal literal atau garis miring terbalik dengan menambahkan garis miring terbalik padanya, tetapi shell juga memperluas karakter ANSI C yang lolos (seperti\n
untuk baris baru,\t
untuk tab, dan\xHH
untuk karakter dengan kode heksadesimalHH
). Namun, jika tidak, mereka berperilaku sebagai string yang dikutip tunggal: tidak ada parameter atau substitusi perintah yang terjadi:Yang penting untuk dicatat adalah bahwa string tunggal yang diterima sebagai argumen ke
echo
perintah persis sama dalam semua contoh ini. Setelah shell selesai mengurai baris perintah, tidak ada cara untuk menjalankan perintah untuk mengetahui apa yang dikutip bagaimana. Bahkan jika itu mau.sumber
$'string'
format POSIX sesuai? Juga, apakah ada nama untuk itu?$'string'
adalah ekstensi non-POSIX, yang saya lihat disebut sebagai "string ANSI"; Saya telah memasukkan fakta-fakta itu ke dalam jawabannya. String semacam itu berfungsi di sebagian besar shell kompatibel-Bourne modern: bash, dash, ksh (baik AT&T dan PD), dan zsh semua mendukungnya.Di bawah ini adalah yang bekerja untuk saya -
sumber
QUOTE
dalam variabel yang terpisah benar-benar berlebihan; Kutipan tunggal di dalam tanda kutip ganda hanyalah karakter biasa. (Juga, jangan gunakan huruf besar untuk variabel pribadi Anda.)EDIT: (Sesuai komentar yang diajukan :)
Saya sudah melihat ini sejak itu. Saya cukup beruntung bahwa saya punya repo berbaring. Masih tidak jelas bagi saya apakah Anda harus menyertakan perintah Anda di antara tanda kutip tunggal dengan paksa. Saya melihat sintaks repo dan saya pikir Anda tidak perlu melakukannya. Anda bisa menggunakan tanda kutip ganda di sekitar perintah Anda, dan kemudian menggunakan tanda kutip tunggal dan ganda apa pun yang Anda butuhkan di dalam asalkan Anda lolos dari tanda kutip ganda.
sumber
cukup gunakan printf
dari pada
gunakan printf untuk mengganti token variabel dengan variabel yang diperluas.
Sebagai contoh:
sumber
printf
tidak benar-benar membelikan Anda apa pun di sini, dan gagal mengutip perintah subsititusi menyebabkan masalah kutipan baru.Variabel dapat berisi tanda kutip tunggal.
sumber
"$myvar"
tanda kutip ganda.Apakah ini Bekerja untukmu?
sumber