Mengapa perintah “echo -e” tampaknya tidak menghasilkan output yang tepat?

21

Di terminal Ubuntu 18.04 LTS, ketika saya menulis perintah ini:

echo -e "Hello\\\n"

Ini memberikan ini sebagai output:

Hello\n

Tetapi harus dicetak, seperti halaman manual mengatakan:

Hello\

Yaitu, pertama cetak Hello, lalu \, kemudian karakter baris baru (dan kemudian baris baru lainnya). Dimana masalahnya?

Lihat beberapa echo -eperintah berikut dan hasilnya :

man420@man420-X542UQ:~$ echo -e "HEllo\a\a\a\a\a\a\\\n"
HEllo\n
man420@man420-X542UQ:~$ echo -e "HEllo\\\n"
HEllo\n
man420@man420-X542UQ:~$ echo -e "HEllo\a\\\n"
HEllo\n
yolin00
sumber
ya.untuk yang pertama 2 \ harus menampilkan \ .dan terakhir \ dan n membuat pelarian backslash \ n (baris baru) .jadi mengapa ia harus mencetak Hello \
yolin00
1
Cobalah tanpa tanda kutip.
ajgringo619
2
Jawaban luar biasa diberikan oleh Eliah Kagan, yang harus Anda terima.
vanadium
2
Jangan gunakan echodi tempat pertama: gunakan printf.
chepner
2
Selalu gunakan tanda kutip tunggal jika Anda ingin memastikan bahwa apa yang Anda tulis adalah tepat apa yang diteruskan ke perintah sebagai argumen.
Giacomo Alzetta

Jawaban:

29

Backslash diperlakukan secara khusus oleh echo -e, tetapi pertama-tama mereka terkadang diperlakukan secara khusus oleh shell (yang dalam hal ini adalah bash), sesuai dengan aturan mengutip shell .

Argumen yang echosebenarnya dilihat adalah Hello\\n. Karena Anda telah lulus -euntuk echo, memperlakukan lolos backslash khusus, dan \\ini jatuh ke satu \. Final ntidak lolos, jadi itu muncul secara harfiah.

Alasan untuk ini adalah bahwa, sebelum dan secara terpisah dari operasi echoitu sendiri, shell memperlakukan \secara khusus dalam beberapa konteks tetapi tidak yang lain. Kuotasi \karakter selalu diperlakukan khusus, dikutip tunggal \ tidak pernah diperlakukan khusus, tetapi pengobatan dikutip ganda \ karakter, seperti dalam perintah yang Anda berlari, lebih halus dan rumit.

Ketika shell menemukan teks kutipan ganda dalam sebuah perintah, seperti halnya "Hello\\\n", shell memperlakukan \sebagai karakter pelarian ketika mendahului karakter yang dengan sendirinya dapat memiliki makna khusus di dalam tanda kutip ganda dan bukan sebaliknya .

  1. Karena \kadang-kadang memiliki makna khusus di dalam "", a \yang segera mendahului yang lain \memiliki efek mengutip yang kedua \. Jadi di dalam tanda kutip ganda, yang pertama \\diciutkan menjadi \.
  2. Setelah dua \karakter pertama , ada \karakter ketiga yang tidak terpengaruh oleh dua karakter pertama dan yang mendahului a n. Tetapi nbukan karakter yang pernah diperlakukan secara khusus di dalam tanda kutip ganda, jadi \sebelum itu tidak diperlakukan secara khusus dalam situasi ini. Dengan demikian \ntetap \n.

Efeknya adalah bahwa, dalam tanda kutip ganda, \\\nditafsirkan sebagai \\n.

Saat echo -edilihat \\n, yang pertama \menghapus makna khusus dari yang kedua, jadi echomencetak \nsecara harfiah untuk teks itu.


Jika tujuan Anda adalah mencetak Hellodengan baris baru ekstra tetapi tidak ada garis miring terbalik (pertanyaannya semula tidak jelas tentang ini, ditambah saya pikir itu adalah contoh yang berguna), maka salah satu solusinya adalah menghapus a \. Menjalankan echo -e "Hello\\n"output Hellodengan baris baru ekstra di akhir.

Solusi yang lebih baik adalah dengan menggunakan tanda kutip tunggal dan menulis echo -e 'Hello\n'. Kutipan tunggal adalah bentuk kutipan terkuat. Solusi yang lebih baik biasanya digunakan printfdaripada echo, yang dalam hal ini adalah printf 'Hello\n\n'.

Jika tujuan Anda adalah mencetak Hello\termasuk garis miring terbalik, diikuti oleh baris baru ekstra , maka pendekatan yang dikutip ganda mungkin dilakukan tetapi rumit. Untuk mengetahuinya, mundur pekerjaan: echo -emualaf \\untuk \dan \nuntuk baris baru, dan bertobat double-mengutip \\untuk \, sehingga Anda dapat melakukannya dengan enam backslashes ( echo -e "Hello\\\\\\n"), karena \\nternyata dalam \nkarena satu backslash melarikan diri lagi. Anda juga dapat melakukannya dengan lima, karena kutip ganda tetap dipertahankan \nketika \tidak lolos.

Ini menggambarkan manfaat dari kutipan tunggal: cukup masukkan apa pun yang Anda ingin echo -elihat di dalam kutipan tunggal ( echo -e 'Hello\\\n'). printfjuga bagus di sini. Salah satu opsi adalah printf 'Hello\\\n\n'. Tetapi yang printfbenar-benar bersinar adalah bahwa Anda dapat memasukkan argumen tambahan. Anda dapat menggunakan printf '%s\n\n' 'Hello\', yang menyisipkan argumen kedua (secara harfiah Hello\karena tanda kutip tunggal tidak mengubah apa pun) sebagai pengganti %s.

Eliah Kagan
sumber