Cara menambahkan baris baru saat menggunakan gema

42

Mengapa perintah berikut tidak memasukkan baris baru dalam file yang dihasilkan dan apa solusinya?

$ echo "Line 1\r\nLine2" >> readme.txt

$ cat readme.txt 
Line 1\r\nLine2
Saeid Yazdani
sumber
6
Apakah echowajib? Anda dapat menggunakan printf.
Archemar
Saya tidak tahu tentang printf, dengan printf berfungsi: P ... lalu apa fungsinya jika tidak bekerja dengan gema?
Saeid Yazdani
Apakah \rtermasuk dalam output atau itu bagian dari CRLFbaris baru?
cuonglm
9
Ada banyak implementasi echoperintah yang berbeda yang tidak kompatibel satu sama lain. Oleh karena itu disarankan untuk menggunakan alat yang lebih standar printf. Lihat unix.stackexchange.com/questions/65803/… untuk tinjauan umum masalah yang lebih luas.
jimmij
Di Stack Overflow, Echo baris baru di Bash mencetak literal \ nEcho baris baru di Bash mencetak literal \ n memiliki beberapa jawaban berguna.
Graham Perrin

Jawaban:

38

echo


Sebuah echoimplementasi yang ketat sesuai dengan Single Unix Specification akan menambahkan baris baru jika Anda lakukan:

echo 'line1\nline2'

Tapi itu bukan perilaku yang bisa diandalkan. Sebenarnya, sebenarnya tidak ada perilaku standar yang dapat Anda harapkan echo.

Operan

string

String yang akan ditulis ke output standar. Jika operan pertama adalah -n, atau jika salah satu operan berisi karakter < \backslash> , hasilnya ditentukan-implementasi .

Pada sistem konforman XSI , jika operan pertama -n, itu harus diperlakukan sebagai string, bukan opsi . Urutan karakter berikut harus diakui pada sistem yang sesuai dengan XSI dalam salah satu argumen:

\a- Tulis <alert> .

\b- Tulis <backspasi> .

\c- Menekan <newline> yang jika tidak mengikuti argumen terakhir di output. Semua karakter yang mengikuti \cargumen akan diabaikan.

\f- Tulis <form-feed> .

\n- Tulis <newline> .

\r- Tulis <carriage-return> .

\t- Tulis <tab> .

\v- Tuliskan <vertical-tab> .

\\- Tulis karakter <backslash> .

\0num- Tulis nilai 8-bit yang merupakan angka oktal nol, satu, dua, atau tiga digit num.

Jadi sebenarnya tidak ada cara umum untuk mengetahui cara menulis baris baru echo, kecuali bahwa Anda biasanya dapat mengandalkan melakukannya echo.

Sebuah bashshell biasanya tidak tidak sesuai dengan spesifikasi, dan menangani -ndan pilihan lain, tapi bahkan yang tidak pasti. Anda dapat melakukan:

shopt -s xpg_echo
echo hey\\nthere

hey
there

Dan bahkan itu tidak perlu jika bashtelah dibangun dengan opsi waktu bangun ...

--enable-xpg-echo-default

Jadikan echobawaan mengembangkan karakter backslash-escaped secara default, tanpa memerlukan -eopsi. Ini menetapkan nilai default dari xpg_echoopsi shell on, yang membuat Bash echoberperilaku lebih seperti versi yang ditentukan dalam Spesifikasi Unix Tunggal, versi 3. Lihat Bash Builtins , untuk deskripsi tentang urutan melarikan diri yang echomengenali.


printf


Di sisi lain, printfperilaku cukup jinak dibandingkan.

ALASAN

The printfutilitas ditambahkan untuk menyediakan fungsionalitas yang secara historis telah disediakan oleh echo. Namun, karena perbedaan yang tak dapat didamaikan dalam berbagai versi yang echomasih ada, versi ini memiliki beberapa fitur khusus, meninggalkan mereka ke printfutilitas baru ini , yang didasarkan pada satu di sistem Edisi Kesembilan.

Bagian DIPERLUASKAN DESKRIPSI hampir sama persis dengan printf()fungsi dalam standar ISO C, meskipun dijelaskan dalam hal notasi format file dalam Notasi Format File XBD .

Ini menangani format string yang menggambarkan argumennya - yang bisa berupa banyak hal, tetapi untuk string cukup banyak baik %bstring yte atau %string literal . Selain dari %formats di argumen pertama, itu berperilaku paling seperti %bargumen string yte, kecuali bahwa itu tidak menangani jalan \ckeluar.

printf ^%b%s$ '\n' '\n' '\t' '\t'

^
\n$^    \t$

Lihat Mengapa printflebih baik daripada echo? untuk lebih.


echo() printf


Anda dapat menulis sesuai standar Anda sendiri echoseperti ...

echo(){
    printf '%b ' "$@\n\c"
}

... yang seharusnya selalu melakukan hal yang benar secara otomatis.

Sebenarnya, tidak ... Itu mencetak literal \ndi bagian akhir argumen jika argumen terakhir berakhir dengan jumlah ganjil <backslashes> .

Tetapi ini tidak:

echo()
    case    ${IFS- } in
    (\ *)   printf  %b\\n "$*";;
    (*)     IFS=\ $IFS
            printf  %b\\n "$*"
            IFS=${IFS#?}
    esac
mikeserv
sumber
+1 untuk shopt -s xpg_echoopsi dalam echountuk digunakan -esecara default.
Vignesh Raja
Solusi ini tidak berfungsi tanpa -e. Saya terkejut bahwa tidak ada yang memperhatikan bahwa kecuali mungkin @HaydeSchiff
ha9u63ar
@ ha9u63ar - uhh ... apakah Anda membaca ini?
mikeserv
27

Lewati tanda -e ke echo untuk mengurai karakter yang lolos seperti "\ r \ n", seperti:

echo -e "Line 1\r\nLine2" >> readme.txt
Hayden Schiff
sumber
Opsi "-e" sederhana yang bagus untuk membuat urutan pelarian berfungsi - ia mengatakan pada jawaban lain yang echotidak dapat diandalkan dan tidak mengikuti standar yang tidak sama printf.
Edward
1
Pastikan skrip Anda tidak mengandung literal \ r \ n, seperti dalam sebuah tr -d "\n"perintah.
Noumenon
8

Di semua versi bash yang saya gunakan, Anda bisa memasukkan baris baru literal ke string baik secara interaktif maupun dalam skrip, asalkan string tersebut cukup dikutip.

Secara interaktif:

$ echo "Line one
> Line two"
Line one
Line two
$

Dalam naskah:

echo "Line one
Line two"
Trauma Digital
sumber
4
echo -e "Line 1\r\nLine2" >> readme.txt

kemungkinan penggunaan lebih lanjut:

man echo
zodo
sumber
2

Orang-orang sudah menjawab dengan cukup, tetapi saya menolak untuk menerima dunia di mana gema menerima pilihan selain -n.

nl='
'
echo Line 1"$nl"Line 2"$nl"Line 3
Staven
sumber
1

Jika Anda memiliki karakter yang bukan bagian dari pesan, Anda dapat menyalurkan melalui sed

$ echo "Time on the next line:@$(date +"%Y-%m-%dT%T%z")" | sed -e's/@/\n/g'
Time on the next line:
2016-03-25T10:12:39-0500
verisimilidude
sumber