Mengapa wc <<< "$ string" menunjukkan panjang satu byte lebih panjang daripada printf "$ string" | toilet?

11

Secara tidak sengaja, saya menemukan bahwa wcpenghitungan berbeda tergantung pada bagaimana ia mendapat input dari bash:

$ s='hello'
$ wc -m <<<"$s"
6
$ wc -c <<<"$s"
6
$ printf '%s' "$s" | wc -m
5
$ printf '%s' "$s" | wc -c
5

Apakah ini - IMHO membingungkan - perilaku didokumentasikan di suatu tempat? Apa yang wcdiperhitungkan di sini - apakah ini asumsi baris baru?

rexkogitans
sumber
3
Anda selalu dapat mengirim ke od -cuntuk melihat persis apa yang Anda miliki.
Thorbjørn Ravn Andersen
Atau, lebih baik xxd -g1,.
Ruslan
1
Saya harap printf "$s"bukan skrip Anda yang sebenarnya ... semoga maksud Andaprintf "%s" "$s"
user541686
Karena ada begitu banyak komentar tentang printf, saya mengedit posting saya untuk mencerminkan praktik terbaik.
rexkogitans

Jawaban:

38

Perbedaan ini disebabkan oleh baris baru yang ditambahkan ke string di sini. Lihat manual Bash :

Hasilnya diberikan sebagai string tunggal, dengan baris baru ditambahkan, ke perintah pada input standarnya (atau deskriptor file n jika n ditentukan).

wc menghitung dengan cara yang sama, tetapi inputnya berbeda.

Stephen Kitt
sumber
7
Jika harus dicatat bahwa untuk mencetak konten (sewenang-wenang) suatu variabel tanpa karakter baris baru yang ditambahkan, itu harus printf %s "$var"(atau print -rn -- "$var"dengan cangkang mirip ksh), bukan printf "$var"yang tidak akan bekerja dengan benar untuk nilai-nilai $varyang mengandung %atau karakter backslash (atau mulai dengan -sebagian besar implementasi).
Stéphane Chazelas
Perhatikan bahwa implementasi di sini-string asli di port Unix rctidak menambahkan karakter baris baru.
Stéphane Chazelas
26

Ini adalah baris baru yang berhasil ditambahkan oleh pengalih-string di sini:

$ s="hello"
$ hexdump -C <<<"$s"
00000000  68 65 6c 6c 6f 0a                                 |hello.|
00000006
$ printf "$s" | hexdump -C
00000000  68 65 6c 6c 6f                                    |hello|
00000005
Murphy
sumber