Terkadang saya melihat skrip shell menggunakan semua cara berbeda untuk mengutip beberapa teks:"..."
, '...'
, $'...'
, dan $"..."
. Mengapa ada begitu banyak jenis kutipan yang digunakan?
Apakah mereka berperilaku berbeda atau memengaruhi apa yang dapat saya lakukan di dalam diri mereka?
Jawaban yang Diterima:
Semua ini berarti sesuatu yang berbeda, dan Anda dapat menulis hal yang berbeda di dalamnya (atau hal yang sama, dengan arti yang berbeda). Berbagai jenis kutipan menafsirkan urutan pelarian yang berbeda di dalamnya (something
), atau melakukan atau tidak mengizinkan interpolasi variabel ($something
) dan jenis ekspansi lain di dalamnya.
Singkatnya:
'...'
sepenuhnya literal."..."
memungkinkan variabel dan karakter kutipan yang disematkan.$'...'
melakukan pelarian karakter sepertin
, tetapi tidak memperluas variabel.$"..."
adalah untuk terjemahan bahasa manusia di Bash dan ksh.
'Kutipan tunggal'
Apa pun yang Anda tulis di antara tanda kutip tunggal diperlakukan secara harfiah dan tidak diproses sama sekali. Garis miring terbalik dan tanda dolar tidak memiliki arti khusus di sana. Ini berarti Anda tidak dapat melakukan backslash-escape karakter (termasuk tanda kutip tunggal lainnya!), menginterpolasi variabel, atau menggunakan fitur shell lainnya.
Semua contoh ini menghasilkan apa yang tertulis di antara tanda kutip:
Kode | Hasil |
---|---|
'hello world' | halo dunia |
'/pkg/bin:$PATH' | /pkg/bin:$PATH |
'hellonworld' | dunia neraka |
'`echo abc`' | `echo abc` |
'I'dn't've' | Aku tidak |
Yang terakhir rumit – ada dua string yang dikutip tunggal berjalan bersama dengan beberapa teks yang tidak dikutip. Yang pertama berisi I
. Teks yang tidak dikutip dn't
berisi satu kutipan yang lolos di tingkat shell , sehingga tidak memulai string yang dikutip dan disertakan sebagai karakter literal (jadi, dn't
). String terakhir yang dikutip hanya ve
. Semua itu digabungkan menjadi satu kata dengan cara kerja shell yang biasa.
Ungkapan yang agak umum untuk menggabungkan teks literal dan variabel adalah menjalankannya bersama-sama seperti itu:
'let x="'$PATH"
akan mengakibatkan
let x="/usr/bin:/bin"
sebagai satu kata (lebih baik kutip ganda $PATH
juga untuk berjaga-jaga – spasi atau karakter globbing dalam variabel nilai mungkin diproses sebaliknya – tetapi demi contoh berjalan yang dapat dibaca, saya belum melakukannya).
“Kutipan ganda”
Di dalam tanda kutip ganda, dua jenis perluasan diproses, dan Anda dapat menggunakan garis miring terbalik untuk menghindari karakter guna mencegah perluasan atau pelepasan agar tidak diproses.
Ada dua kategori ekspansi yang terjadi di dalam tanda kutip ganda:
- Yang dimulai dengan
$
(ekspansi parameter$abc
dan${abc}
, substitusi perintah$(...)
, dan ekspansi aritmatika$((...))
); - Substitusi perintah dengan backquotes
`abc`
;
Di dalam tanda kutip, garis miring terbalik dapat menghambat ekspansi tersebut dengan meletakkannya sebelum $
atau `
. Itu juga dapat menghindari tanda kutip ganda penutup, jadi "
hanya menyertakan "
di string Anda, atau garis miring terbalik lainnya. Garis miring terbalik lainnya dipertahankan secara harfiah – tidak ada pelarian untuk menghasilkan karakter lain, dan tidak dihapus.
Beberapa contoh ini bertindak berbeda dari sebelumnya, dan beberapa tidak:
Kode | Hasil |
---|---|
"hello world" | halo dunia |
"/pkg/bin:$PATH" | /pkg/bin:/bin:/usr/bin |
"hellonworld" | dunia neraka |
"hello\nworld" | dunia neraka |
"`echo abc`" | abc |
"I'dn't've" | Saya tidak akan |
"I'dn't've" | Saya tidak akan |
"I"dn"t've" | Saya belum |
$'ANSI-C mengutip'
Kutipan semacam ini memungkinkan pelolosan garis miring terbalik gaya-C untuk diproses, tetapi tidak variabel atau substitusi yang disematkan. Ini satu-satunya jenis kutipan yang mendukung karakter lolos .
Ini adalah ekstensi dari ksh, sekarang didukung di Bash, zsh, dan beberapa shell lainnya juga. Ini belum menjadi bagian dari standar POSIX dan skrip portabel maksimal tidak dapat menggunakannya, tetapi skrip Bash atau ksh gratis untuk digunakan.
Semua escape ini dapat digunakan dengan arti C-nya:a
, b
, f
, n
, r
, t
, v
, dan literal lolos \
, '
, "
, dan ?
. Mereka juga mendukung ekstensi e
(karakter pelarian) dan di Bash dan ksh cx
(apa yang akan dimasukkan Ctrl-x, misalnya cM
adalah pengangkutan kembali). Shell memiliki berbagai ekstensi minornya sendiri.
Ini juga memungkinkan empat jenis karakter umum lolos:
nnn
, satu byte dengan nilai oktal nnnxHH
, satu byte dengan nilai heksadesimal HHuHHHH
, titik kode Unicode yang indeks heksadesimalnya HHHHUHHHHHHHH
, titik kode Unicode yang indeks heksadesimalnya HHHHHHH
Semua digit itu opsional setelah yang pertama.
$
dan `
tidak memiliki arti dan dipertahankan secara harfiah, jadi Anda tidak dapat menyertakan variabel di sana.
Kode | Hasil |
---|---|
$'hello world' | halo dunia |
$'/pkg/bin:$PATH' | /pkg/bin:$PATH |
$'hellonworld' | halo dunia |
$'`echo abc`' | `echo abc` |
$'I'dn't've' | Saya tidak akan |
$'U1f574u263A' | 🕴☺ |
Sebagian besar pelarian ini dapat Anda simulasikan menggunakan printf
perintah, meskipun POSIX hanya membutuhkan \
, a
, b
, f
, n
, r
, t
, v
, dan nnn
untuk bekerja di sana. Anda dapat menggunakan substitusi perintah untuk menyematkan printf
di dalam tanda kutip ganda jika diperlukan:"Path:$(printf 't')$PATH"
.
$”Terjemahan lokal”
Ini adalah ekstensi khusus ksh dan Bash untuk melokalisasi string tekstual bahasa alami, dan mencari bagian di dalam tanda kutip dalam katalog pesan. Ini melakukan semua ekspansi kutipan ganda terlebih dahulu. Jika string tidak ditemukan dalam database terjemahan, string akan digunakan sebagai terjemahannya sendiri. Asumsi bawaan adalah bahwa string dalam bahasa Inggris.
Anda mungkin tidak ingin menggunakan yang ini, tetapi jika Anda melihatnya, Anda biasanya dapat memperlakukannya sebagai tanda kutip ganda biasa.
Satu hal yang perlu diperhatikan adalah bahwa tidak ada tidak jenis kutipan yang memungkinkan ekspansi parameter yang disematkan dan karakter yang disematkan lolos. Dalam kebanyakan kasus di mana Anda menginginkannya, Anda akan lebih baik (lebih aman) menggunakan printf
:
printf 'New path: e[1m%se[0m' "/pkg/bin:$PATH:"
Ini dengan jelas memisahkan bagian mana yang tunduk pada pelolosan karakter dan mana yang merupakan nilai data.
Lain adalah bahwa semua gaya kutipan ini membuat satu "kata" di shell, kecuali [email protected]
atau perluasan larik ${x[@]}
digunakan di dalam tanda kutip ganda. Kedua bentuk kutipan tunggal selalu satu kata dan tidak pernah diperluas lebih jauh.