Warum zeigt wc <<< “$ string” eine um ein Byte längere Länge als printf “$ string” | Toilette?

11

Aus Versehen habe ich herausgefunden, dass dies wcunterschiedlich zählt, je nachdem, wie es die Eingabe von bash erhält:

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

Ist dieses - meiner Meinung nach verwirrende - Verhalten irgendwo dokumentiert? Was wczählt hier - ist dies eine angenommene Newline?

Rexkogitans
quelle
3
Sie können jederzeit pfeifen, od -cum genau zu sehen, was Sie haben.
Thorbjørn Ravn Andersen
Oder besser xxd -g1.
Ruslan
1
Ich hoffe, printf "$s"ist nicht Ihr eigentliches Skript ... hoffentlich meinten Sieprintf "%s" "$s"
user541686
Da es so viele Kommentare zu printf gab, habe ich meinen Beitrag bearbeitet, um die besten Praktiken widerzuspiegeln.
Rexkogitans

Antworten:

38

Der Unterschied wird durch eine neue Zeile verursacht, die der hier angegebenen Zeichenfolge hinzugefügt wird. Siehe das Bash-Handbuch :

Das Ergebnis wird als einzelne Zeichenfolge mit einem Zeilenumbruch an den Befehl in seiner Standardeingabe (oder in den Dateideskriptor n, wenn n angegeben ist) geliefert .

wc zählt auf die gleiche Weise, aber seine Eingabe ist unterschiedlich.

Stephen Kitt
quelle
7
Wenn beachtet werden sollte, dass der (beliebige) Inhalt einer Variablen ohne ein hinzugefügtes Zeilenumbruchzeichen gedruckt werden soll printf %s "$var"(oder print -rn -- "$var"mit ksh-ähnlichen Shells), printf "$var"was für Werte $var, die %Zeichen oder Backslash-Zeichen enthalten (oder ) nicht korrekt funktionieren würde Beginnen Sie mit den -meisten Implementierungen.
Stéphane Chazelas
Beachten Sie, dass die ursprüngliche Here-String-Implementierung im Unix-Port von rcdieses Zeilenumbruchzeichen nicht hinzugefügt hat.
Stéphane Chazelas
26

Es ist eine nachfolgende Newline, die vom Here-String-Redirector hinzugefügt wurde:

$ 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
quelle