Mengapa tilde (~) tidak berkembang di dalam tanda kutip ganda?

54

Menurut jawaban ini dan pemahaman saya sendiri, tilde memperluas ke direktori home:

$ echo ~
/home/braiam

Sekarang, setiap kali saya ingin ekspansi shell berfungsi, yaitu menggunakan nama variabel seperti itu $FOO, dan jangan merusak karakter yang tidak terduga, spasi seperti itu, dll. Orang harus menggunakan tanda kutip ganda ":

$ FOO="some string with spaces"
$ BAR="echo $FOO"
$ echo $BAR
echo some string with spaces

Mengapa ekspansi ini tidak berhasil dengan tilde?

$ echo ~/some/path
/home/braiam/some/path
$ echo "~/some/path"
~/some/path
Braiam
sumber
3
Perhatikan juga bahwa ini memiliki ketidakkonsistenan saat memberikan argumen program pada baris perintah yang pada argumen perintah --path ~/myfilediperluas tetapi --path=~/myfiletidak.
Ángel
Terkait: Apakah ~ selalu sama $ HOME
Stéphane Chazelas
Variasi pada tema ini adalah unix.stackexchange.com/questions/279565 .
JdeBP

Jawaban:

45

Alasannya, karena di dalam tanda kutip ganda, tilde ~tidak memiliki arti khusus, itu diperlakukan sebagai literal.

POSIX mendefinisikan Kutipan Ganda sebagai:

Menutup karakter dalam tanda kutip ganda ("") akan mempertahankan nilai literal semua karakter dalam tanda kutip ganda, dengan pengecualian tanda dolar, backquote, dan garis miring terbalik karakter,

...

Aplikasi harus memastikan bahwa penawaran ganda didahului oleh backslash untuk dimasukkan dalam penawaran ganda. Parameter '@' memiliki arti khusus di dalam tanda kutip ganda

Kecuali $, `, \dan @, lain-lain karakter diperlakukan sebagai tanda kutip ganda dalam literal.

cuonglm
sumber
9
Dalam hal ini saya kira Anda harus menggunakan $HOME.
Seth
11
Atau Anda bisa saja tidak mengutip ~, misalnyals -l ~/"My Documents"
Andrew Medico
Ini sangat tidak intuitif. Apa alasan mereka memilih melakukan ini? (Jawaban ini sebenarnya tidak memberikan alasan, tetapi hanya menunjuk pada standar, tetapi mungkin standar ditulis seperti itu karena suatu alasan .)
iconoclast
1
@iconoclast jika Anda benar-benar menginginkan "mengapa mereka diterapkan dengan cara ini" bacalah jawaban Stephane .
Braiam
2
Jadi, @iconoclast, mengapa adalah langit biru? :) :) :)
Jesse Chisholm
32

Ekspansi Tilde didefinisikan oleh POSIX sebagai:

"Tilde-prefix" terdiri dari karakter <tilde> yang tidak dikutip di awal kata, diikuti oleh semua karakter sebelum <slash> tanpa tanda kutip pertama dalam kata, atau semua karakter dalam kata jika tidak ada < slash>. Dalam penugasan, beberapa awalan-tilde dapat digunakan: [...] mengikuti <equals-sign> dari penugasan, mengikuti sembarang kutipan <colon>, atau keduanya. [...] Jika tidak ada karakter dalam awalan tilde yang dikutip, karakter dalam awalan tilde mengikuti <tilde> diperlakukan sebagai nama login yang mungkin dari basis data pengguna. [...] Jika nama loginnya nol (yaitu, awalan tilde hanya berisi tilde), awalan tilde digantikan oleh nilai variabel HOME. Jika HOME tidak disetel, hasilnya tidak ditentukan. [...]

Jadi jawaban terpendek adalah "karena itu didefinisikan seperti itu": mengutip salah satu karakter dalam awalan, termasuk ~, menekan ekspansi.

Itu juga mendefinisikan ekspansi seperti biasa menghasilkan satu kata, jadi mengutip tidak perlu:

Pathname yang dihasilkan dari ekspansi tilde harus diperlakukan seolah dikutip untuk mencegahnya diubah oleh field splitting dan ekspansi pathname.

Jika beberapa lintasan membutuhkan kuotasi, tetapi sisanya adalah awalan tilde, Anda dapat menggabungkan ekspansi tilde dan mengutip biasa dengan mudah:

$ cat ~/"file name with spaces"

Pada "mengapa" yang lebih luas: karena tidak ada kegunaan yang mungkin untuk pemisahan kata ~, itu harus menjadi perilaku default, daripada mengharuskannya untuk dikutip. Karena tidak perlu mengutipnya, memberikan ~arti khusus di dalam kutipan akan menjadi komplikasi yang tidak perlu. Dan, tentu saja, alasan historis berarti itu tidak dapat diubah sekarang bahkan jika itu diinginkan.

Michael Homer
sumber
Menurut panduan bash ini , ekspansi tilde terjadi sebelum pemisahan spasi putih. Apakah ada cara untuk melakukan ekspansi tilde dengan aman, bahkan jika direktori home Anda memiliki ruang kosong di dalamnya? Biasanya, tentu saja, Anda akan melakukan hal semacam ini dengannya "".
Lucretiel
Ekspansi adalah satu kata; lihat kutipan ayat kedua dalam jawabannya.
Michael Homer
23

~ Berasal dari C-shell, jauh sebelum ditambahkan ke shell Korn dan kemudian ditambahkan ke spesifikasi shell POSIX.

Dalam C-shell, ~adalah operator globbing (diperluas dengan rutin yang sama dengan yang berkembang *.txtmisalnya), jadi seperti sisa globbing tidak dilakukan dalam tanda kutip ganda.

Stéphane Chazelas
sumber
11

Meskipun ini tidak menjawab mengapa itu dirancang seperti itu, Anda menggunakannya $HOMEsebagai gantinya jika Anda perlu menggantinya, karena itulah dasarnya ~.

$ echo "$HOME/some/path"
/home/braiam/some/path
berbaur
sumber
6
ini tidak bekerja dengan~otheruser
Johannes Kuhn
2
Benar, tetapi Anda bisa melakukannya: MEREKA = ~ pengguna lain kemudian menggunakan "$ MEREKA / beberapa / path"
melds
1
Solusi untuk ~otherusermenunjukkan betapa buruknya memperlakukan ~berbeda dari variabel dan hal-hal lain yang diperluas dalam tanda kutip ganda.
iconoclast