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


3
Perhatikan juga bahwa ini memiliki ketidakkonsistenan saat memberikan argumen program pada baris perintah yang pada argumen perintah --path ~/myfilediperluas tetapi --path=~/myfiletidak.
Ángel



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.


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.


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.


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

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
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.