Bagaimana echo
dan printf
memperlakukan backslashes di zsh
, bash
dan kerang lainnya?
Di bawah zsh saya mendapatkan perilaku berikut:
$ echo "foo\bar\baz"
foaaz
$ echo "foo\\bar\\baz"
foaaz
$ echo 'foo\bar\baz'
foaaz
$ echo 'foo\\bar\\baz'
foo\bar\baz
Di bawah bash , segalanya tampak sedikit lebih konsisten:
bash$ echo "foo\bar\baz"
foo\bar\baz
bash$ echo 'foo\bar\baz'
foo\bar\baz
bash$
Tetapi yang lebih konkret: Bagaimana saya bisa meneruskan string yang mengandung garis miring terbalik seperti\\foo\bar\something
ke:
echo
printf
print
dan mendapatkan string yang sama persis? (dalam zsh
dan bash
)?
Berikut ini eksperimen lain dengan fungsi di zsh:
function foo
{
echo -E '$1'
}
$ foo \\here\is\some\path
$1
Bagaimana saya bisa mencetaknya \\here\is\some\path
?
Pembaruan (Catatan: ini sekarang telah dijawab dalam komentar Stephane)
Saya sudah mencoba yang berikut ini di zsh 5.0.2:
function foo
{
printf '$s\n' $1
}
foo '\\some\path'
Tapi ini dicetak $s
?
printf
,echo
tidak portabel dalam hal ini.'
dengan"
, dan aktifkan dengan: foo '\\ here \ is \ some \ path' (jika tidak, shell pemanggil mendapat kesempatan untuk menafsirkan '\' sebelum mereka sampai ke fungsinya)'$s\n'
saat seharusnya digunakan'%s\n'
.Jawaban:
zsh
echo
berperilaku dengan cara standar, sepertibash
dalam mode UNIX. Itu memperluas\b
ke karakter ASCII BS seperti spesifikasi UNIX membutuhkan.Jangan gunakan
echo
untuk menampilkan string acak, gunakanprintf
:print -r -- "$1"
juga bekerja tetapiksh
/zsh
spesifik.echo -E - "$1"
bekerja denganzsh
dan saya percaya beberapa BSD.bekerja di shell seperti Bourne bahkan dari beberapa dekade ketika tidak ada
printf
perintah tapi itu menelurkan proses baru, dan benar-benar tidak diperlukan saat ini seperti yang kita miliki diprintf
mana - mana.Dan omong-omong, Anda perlu melarikan diri garis miring terbalik pada baris perintah shell karena khusus untuk shell (setiap shell tetapi
rc
), jadi:foo \\foo\bar
akan meneruskan"\foo\bar"
stringfoo
yang tidak dapat menemukan kembali backslash yang hilang kembali.sumber
printf '%s\n' "$var"
bekerja untuk saya di baris perintah (zsh 5.0.2
, yaitu yang terbaru), tetapi tidak di dalam suatu fungsi (lihat pembaruan saya di OP). Mengapa?printf '%s\n'
, bukan yangprintf '$s\n'
kamu inginkan. Perhatikan bahwa Anda perlu mengutip variabel dalam shell lain selainzsh
("$1"
, bukan$1
) dan sintaks definisi fungsi standar adalahfoo() { ...; }
, meskipun shell apa pun kecualibash
diizinkanfoo() any-command
, danfunction foo { .... }
adalahksh
sintaksnya.jawaban baru: baca -r var
dan untuk ditampilkan:
harus bekerja.
Jadi untuk fungsi foo Anda:
jawaban lama di bawah (tidak menjawab, tapi mungkin berguna ^^)
cukup ganti masing-masing
\
dengan\\
memberi tahu shell "bahwa itu benar-benar\
saya inginkan". jika tidak (misalnya dalam zsh, dalam contoh Anda) bisa jadi itu\b
berarti "1 backspace", atau apa pun.Anda bisa misalnya menggunakan sed:
(lihat bagaimana Anda juga perlu melarikan diri "\" di sana, untuk memberi tahu sed hal yang sama: "itu adalah literal" \ "Saya ingin) (dan perhatikan saya mengelilinginya dengan '' dan bukan" "untuk menghindari shell untuk menafsirkan sebagian besar juga)
sumber
read -r var
sepertinya menunggu masukan dariSTDIN
. Bagaimana jika saya menyampaikannya sebagai argumen? (mis. foo\\here\is\some\path
)Secara umum Anda tidak bisa, karena backslash adalah karakter pelarian (dan karenanya harus melarikan diri ketika nilai literalnya diperlukan). BASH memberikan penawaran tunggal untuk tujuan ini, namun Anda tidak dapat menggunakan escape quote tunggal dalam string yang dikutip tunggal.
Adapun
echo
perbedaan, itu adalah built-in yang mungkin berperilaku berbeda di shell (sampai batas tertentu). Misalnya BASH built-in memiliki-e
opsi yang memerintahkannya untuk menginterpretasikan urutan backslash - dengan itu Anda akan mendapatkan perilaku yang Anda lihat di shell Z.sumber