Mengapa bash di sini-string menambahkan char baris baru yang tertinggal?


34

Contoh berikut menunjukkan bahwa baris baru ditambahkan ke string di sini .
Mengapa ini dilakukan?

xxd -p <<<'a'  
# output: 610a

xxd -p <<<'a
'
# output: 610a0a

Jawaban:


38

Jawaban yang mudah adalah karena ksh ditulis seperti itu (dan bash kompatibel). Tapi ada alasan untuk pilihan desain itu.

Sebagian besar perintah mengharapkan input teks. Di dunia unix, file teks terdiri dari urutan baris, masing-masing berakhir pada baris baru . Jadi, dalam kebanyakan kasus, baris akhir final diperlukan. Kasus yang sangat umum adalah untuk mengambil output dari perintah dengan susbtitusi perintah, memprosesnya dengan cara tertentu, kemudian meneruskannya ke perintah lain. Substitusi perintah menghapus baris baru; <<<menempatkan satu kembali.

tmp=$(foo)
tmp=${tmp//hello/world}
tmp=${tmp#prefix}
bar <<<$tmp

Bash dan ksh toh tidak bisa memanipulasi data biner (tidak bisa mengatasi karakter nol), jadi tidak mengherankan bahwa fasilitas mereka diarahkan untuk data teks.

<<<Sintaks di sini-string sebagian besar hanya untuk kenyamanan, seperti <<dokumen-dokumen di sini. Jika Anda tidak perlu menambahkan baris baru final, gunakan echo -n(dalam bash) atau printfdan saluran pipa.


Jauh lebih teliti daripada jawaban saya.
Mike

2
Bash mungkin telah meminjam sini-string dari ksh93, tapi ksh pada gilirannya meminjam mereka dari zsh, yang mendapatkannya dari Plan 9 shell rc .
Mark Reed

2
<<<diperkenalkan ke dunia Bourne oleh zsh, bukan ksh. Dan itu terinspirasi oleh operator serupa di port Unix rcyang tidak menambahkan karakter baris baru tambahan. Menariknya, =(<<<text)operator tidak menambahkan baris baru itu di zsh.
Stéphane Chazelas

Jika Anda bertanya-tanya tentang minat pada jawaban ini adalah karena pertanyaan ini di SO .
fedorqui

1
Apakah ada cara untuk menulis string di sini (tanpa menggunakan utilitas lain seperti printf, dll) menghindari baris baru tailing bash? Seperti @ StéphaneChazelas runcing dimungkinkan di zsh.
CTodea

3

Salah satu skenario di mana praktis untuk memiliki baris baru ditambahkan ke sini-string adalah ketika menggunakan readperintah ketika set -emode aktif. Ingat bahwa set -emenyebabkan skrip berakhir ketika (lebih atau kurang) menemukan pernyataan yang menghasilkan kode status tidak nol. Pertimbangkan yang readmenghasilkan kode status non-nol ketika menemukan string tanpa baris baru:

#!/bin/bash
set -e

# The following statement succeeds because here-strings append a newline:
IFS='' read -r <<< 'newline appended'
echo 'Made it here'

# The following statement fails because 'read' returns a non-zero status
# code when no newlines are encountered.
printf 'no newline' | IFS='' read -r
echo 'Did not make it here'

-3

Saya pikir itu satu-satunya cara untuk mendapatkan baris baru di akhir-string di sini, bukti:

xxd <<<`echo -ne "a\n"`

Akan terlihat bahwa operator di sini-string menghapus baris baru kecuali mereka diberikan dalam sintaks yang Anda kirimkan.


4
Substitusi perintah itulah yang menghapus baris terakhir. Anda dapat menyederhanakan ini menjadi xxd <<<$(echo a).
Gilles 'SO- stop being evil'
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.