Seperti contoh berikut, dan seperti pada pertanyaan saya baru-baru ini Di bash, kemana pergilah baris char baris baru? , Saya ingin tahu "mengapa" itu terjadi
x="$(echo -ne "a\nb\n")" ; echo -n "$x" | xxd -p
# Output is: 610a62
# The trailing newline from the 'echo' command
# has been "deleted" by Command Substitution
Saya berasumsi pasti ada beberapa alasan yang sangat signifikan untuk tindakan shell, yaitu Substitusi Perintah, untuk benar-benar menghapus beberapa data dari output perintah yang digantikannya ...
tapi saya tidak bisa mendapatkan kepalaku di sekitar yang satu ini, karena tampaknya menjadi kebalikan dari apa yang seharusnya dilakukan .. yaitu. untuk meneruskan output dari sebuah perintah kembali ke proses skrip ... Menahan satu karakter tampaknya aneh bagi saya, tapi saya kira ada alasan yang masuk akal untuk itu ... Saya ingin mengetahui apa alasannya .. .
Jawaban:
Karena shell pada awalnya tidak dimaksudkan sebagai bahasa pemrograman penuh.
Cukup sulit untuk menghapus trailing
\n
dari beberapa output perintah. Namun, untuk tujuan tampilan, hampir semua perintah mengakhiri outputnya\n
, jadi ... harus ada cara sederhana untuk menghapusnya ketika Anda ingin menggunakannya dalam perintah lain. Penghapusan otomatis dengan$()
konstruksi adalah solusi yang dipilih.Jadi, mungkin Anda akan menerima pertanyaan ini sebagai jawaban:
Dapatkah Anda menemukan cara sederhana untuk menghapus trailing
\n
jika ini tidak dilakukan secara otomatis pada perintah berikut?Perhatikan bahwa kutipan diperlukan untuk mencegah hancurnya spasi ganda yang mungkin muncul pada tanggal yang diformat.
sumber
shopt
untuk mengubah perilaku default yang dijelaskan, maka saya akan senang lagi ... Saya merasa sulit untuk berpikir bahwa Bash / Linux / Unix akan mencemari fungsi kritis seperti "menangkap stdout" hanya karenadate
tidak memiliki a dengan / tanpa opsi '\ n' ... Perbaikan yang jelas adalah bahwa bash (atau shell lain) memilikishopt
untuk ini ... Apakah Anda tahu ada? .. dan apakah Anda memiliki tautan referensi yang berbicara tentang mengapa dan di mana penerbitan ini? ... dan mengapa tidakdate
memiliki opsi \ n .. Seharusnya!$()
sintaks alternatif yang disukai .{ echo -n "The current date is "; var="$(date; echo -e x)"; var="${var%x}"; echo -n "$var"; echo ", have a good day!"; }
.. jadi itu :)date
akan bekerja, tapi saya hanya menggunakandate
sebagai contoh dari perintah apa pun ..Itu bagian dari standar :
Tentu saja, standarnya mungkin ditulis dengan cara ini karena begitulah caranya
ksh
atau sesuatu, tetapi itu adalah standar, dan itu adalah perilaku yang terdokumentasi. Jika Anda tidak menyukainya, gunakan Perl atau yang lain yang akan membuat Anda tetap mengikuti baris baru.sumber
Yah, itu masuk akal bagi saya. Baris baru hanya ada di tempat pertama, dalam output perintah normal, sehingga prompt muncul setelah perintah selesai pada baris baru. Baris baru bukan bagian dari output asli dalam banyak kasus, itu ada di sana untuk merapikan layar. Saat Anda mem-parsing output dari sebuah perintah, baris baru di bagian akhir biasanya merepotkan. Mengapa
wc
perintah menghasilkan 2 baris teks? Oh, tidak, itu output yang diikuti oleh baris baru. Ketika Anda menguraikanwc
Anda tidak ingin khawatir tentang fakta bahwa ada 2 baris output - tidak ada benar-benar, hanya ada satu.sumber
\n
dalamstdout
aliran asli dihapus oleh Substitusi Perintah. yaitu. data asli saya (data yang sangat penting) telah menghapus baris baru, bahkan ketika data tersebut dibungkus dengan "tanda kutip". Saya cukup memahami bagaimana dan mengapa Pemisahan Kata berfungsi, tapi saya sama sekali tidak tahu mengapa Command Substitusi hanya melucuti baris baru dan hanya yang tertinggal .Saya mengalami masalah yang sama, dan menemukan contoh di bawah ini. Tampaknya mengutip membantu situasi, setidaknya itu berlaku untuk saya:
http://tldp.org/LDP/abs/html/commandsub.html .
sumber
$str
,, yang berisi string"a b c"
. Jika Anda lulus$str
keecho
tanpa tanda kutip (echo $str
),echo
akan menerimaa
,b
danc
tiga argumen yang terpisah. Shell Anda tidak peduli dengan spasi putih di antara argumen.echo
kemudian akan mencetak argumen tersebut dengan spasi yang memisahkan masing-masing, sehingga Anda dapat"a b c"
. Jika Anda meneruskan variabel keecho
dengan tanda kutip di sekitarnya (echo "$str"
), shell melihatnya sebagai satu argumen danecho
menerimanya seperti itu, sehingga spasi putih tidak runtuh. Hal yang sama berlaku untuk baris baru.-n
flag,echo
tambahkan baris baru pada outputnya, sehingga kedua gema dalam contoh Anda memiliki baris baru. Namun, jika Anda mencobaecho -n $dir_listing
atauecho -n "$dir_listing"
, Anda akan melihat bahwa tidak ada baris baru yang tertinggal dicetak dengan atau tanpa tanda kutip$dir_listing
, yang menunjukkan bahwa masalahnya adalah dengan substitusi perintah.mengapa
echo "hello "
(tanpa tanda kutip) melahap ruang? nilai karakter IFS dilihat oleh shell sebagai pembatas, oleh karena itu, karakter trailing (yang tidak membatasi apa pun) sedang dihapus. commend substitution hanya mengeksekusi commend di sub-shell, jadi ia mengikuti logika yang sama.sumber
x="hello "
danx="hello "
akan kehilangan semua spasi tambahannya jika ditampilkan melaluiecho $x
... Namun hanya baris baru terakhir dari Substituton Perintah yang hilang.IFS
tidak ada hubungannya dengan menelanjangi baris baru di akhir penggantian perintah.