Apakah ada cara untuk menghindari tanda kutip tunggal di shell?

11

E. g. Saya ingin mengatakan

perl -e 'print '"'"'Hello, world!'"'"', "\n";'

Apakah ada cara yang kurang canggung untuk melakukannya, misalnya melarikan diri dari tanda kutip tunggal?

Ya, saya tahu saya bisa menulis

perl -e 'print q[Hello, world!], "\n"'
perl -e 'print "Hello, world!\n"'

Tetapi pertanyaan ini adalah tentang mengutip di shell, bukan di Perl.

Saya tertarik bagaimana melakukannya bashdan cshsejak awal.

codeholic
sumber

Jawaban:

9

Dennis menunjukkan alternatif yang biasa dalam jawabannya (string single-in-double, double-in-single, tunggal dikutip digabungkan dengan kutip tunggal lolos; Anda telah menyebutkan operator kutipan yang dapat disesuaikan dari Perl), tetapi mungkin ini adalah jawaban langsung yang Anda cari untuk.

Dalam cangkang Bourne-like (sh, ksh, ash, dash, bash, zsh, dll.) String yang dikutip tunggal sepenuhnya literal. Ini membuatnya mudah untuk memasukkan karakter yang shell akan perlakukan secara khusus tanpa harus menghindarinya, tetapi itu berarti bahwa karakter kutipan tunggal itu sendiri tidak dapat dimasukkan ke dalam string kutipan tunggal.

Saya bahkan menolak untuk berpikir tentang shell tipe csh karena mereka benar-benar rusak dalam hal lain (lihat Pemrograman Csh Dianggap Berbahaya ).

Chris Johnsen
sumber
Terima kasih. "Ini tidak mungkin" - itu adalah jawaban yang saya harapkan :) Meskipun saya selalu berharap bahwa di sinilah dokumen yang didedikasikan untuk memainkan peran ini.
codeholic
Tidak seperti di Perl, dokumen shell mirip Bourne hanya berguna secara langsung untuk memberikan input melalui stdin. Anda bisa, tentu saja, memasukkan satu tanda kutip di dalamnya. Anda juga dapat mengaktifkan "mode literal" dari dokumen di sini dengan mengutip kata: (mis blah <<\EOF … EOF. ) . Anda juga dapat menggunakan <<'EOF'dan <<"EOF. Mereka semua secara harfiah berarti dokumen di sini (tidak seperti Perl). Jika Anda benar-benar bertekad, Anda bisa melakukannya blah "$(cat<<\EOF … EOF )" other args(menggunakan baris baru di mana saya telah menulis spasi di substitusi perintah; ksh dan zsh dapat melakukannya tanpa kucing , yang lain membutuhkannya). Tetapi apakah itu benar-benar layak?
Chris Johnsen
Hanya ingin mencatat bahwa zsh single quotes tidak cukup literal. Zsh akan mencoba menafsirkan '\ U' di mana saja dalam string yang dikutip tunggal sebagai kode karakter, misalnya echo '\U0000068\U000069'gema 'hai'. Tidak yakin mengapa meskipun kecuali itu adalah bug di shell.
Matius
1
@ Matthew: Penafsiran \Udalam kasus itu sedang dilakukan oleh perintah gema-E bawaan (perilaku ini dapat dikontrol oleh atau opsi BSD_ECHO dan -e). Anda dapat melihat bahwa string literal dilewatkan (dan tidak diartikan sebaliknya) dalam perintah lain; mis printf %s\\n '\U0000068\U000069'.
Chris Johnsen
@ ChrisJohnsen Terima kasih, saya baru di zsh dan tidak menyadari ini, tetapi Anda benar. Halaman manual mengatakan kepada saya -e adalah default tetapi zsh harus menimpanya.
Matius
5

Bagi saya, semua contoh Anda menghasilkan:

Halo Dunia!

Demikian juga ini:

perl -e 'print "Hello, world!", "\n";'

Dan ini:

perl -e 'print '\''Hello, world!'\'', "\n";'

Bisakah Anda mengklarifikasi apa yang Anda coba lakukan?

Dalam shell, seperti Bash, jika Anda ingin mencetak tanda kutip sebagai bagian dari string, satu jenis kutipan lolos dari yang lain.

$ echo '"Hello, world!"'
"Hello, world!"
$ echo "'Hello, world!'"
'Hello, world!'

Edit:

Inilah cara lain:

$ perl -e 'print "\047Hello, world!\047", "\n";'
'Hello, world!'
$ echo -e "\047Hello, world! \047"
'Hello, world! '

Ruang setelah titik seru menghindari kesalahan ekspansi riwayat. Saya bisa melakukannya set +Hsebagai gantinya.

Dijeda sampai pemberitahuan lebih lanjut.
sumber
1

Tidak yakin apakah edit saya ke jawaban sebelumnya akan muncul:

Menempelkan yang sama dengan jawaban baru:

Pendekatan alternatif:

Ketika saya mencoba solusi Anda saya masih tidak bisa mendapatkan 'dicetak.

Tetapi saya mengambil petunjuk dari solusi Anda dan mencoba yang berikut:

$ perl -e '$foo = chr(39); print "${foo}Hello, world ${foo}", "\n";'
'Hello, world '

Nilai ASCII dari 'adalah 39.

Saya membutuhkan ini untuk membuat inline edit ke banyak file untuk ditambahkan 'di lokasi yang menarik.

Kaushik B
sumber
1

Di sini, dokumen adalah cara terbaik untuk tidak peduli untuk melarikan diri:

$ cat <<EOF
my $var = "Hello";
print $text, ', world!', "\n";'
EOF

Anda dapat benar-benar menggagalkan semua ekspansi dengan menggunakan dokumen yang dikutip di sini:

$ cat <<'EOF'
my $var = "Hello";
print $text, ', world!', "\n";'
EOF

Jika Anda ingin meneruskannya sebagai argumen alih-alih input, Anda dapat menggunakan xargs:

$ xargs -0 <<'EOF' perl -e
my $var = "Hello";
print $text, ', world!', "\n";'
EOF
Jérôme Pouiller
sumber
0

Saya tidak tahu apakah ada opsi untuk melakukan ini di bash, tetapi dengan zsh Anda dapat menggunakan ''setelah mengaktifkan RC_QUOTESopsi. (Saya akan merekomendasikan mencoba zsh; kebanyakan bash-kompatibel dan dapat meniru bash untuk kompatibilitas yang lebih banyak lagi.)

Dengan bash (dan masih sebagian besar waktu dengan zsh), saya hanya menggunakan '\''karena lebih mudah dibaca daripada '"'"'.

Saya sama sekali tidak tahu bagaimana melakukannya di csh.

SilverWolf - Pasang kembali Monica
sumber
-1

Anda dapat menggunakan \ 'dan \ "untuk menghindari tanda kutip dengan perl jika digunakan secara internal sebagai bagian dari skrip perl. Saya tidak yakin apakah baris perintah akan menerimanya. Anda dapat mencobanya dan melihat apakah itu berfungsi.

Mikha
sumber
3
Jika itu mudah, saya tidak akan bertanya. Anda dapat mencobanya dan melihat apakah itu berfungsi sebelum mengirim jawaban.
codeholic