Por que wc <<< "$ string" mostra um comprimento de um byte a mais do que printf "$ string" | banheiro?

11

Accidentially, eu descobri que wcconta diferentemente dependendo de como obtém a entrada do bash:

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

Esse comportamento - IMHO confuso - está documentado em algum lugar? O que wcconta aqui - essa é uma nova linha assumida?

rexkogitans
fonte
3
Você sempre pode canalizar od -cpara ver exatamente o que tem.
Thorbjørn Ravn Andersen
Ou melhor xxd -g1.
Ruslan
1
Esperança que printf "$s"não é o seu próprio script ... espero que você quis dizerprintf "%s" "$s"
user541686
Como havia muitos comentários sobre o printf, editei minha postagem para refletir as melhores práticas.
rexkogitans 31/01

Respostas:

38

A diferença é causada por uma nova linha adicionada à string here. Veja o manual do Bash :

O resultado é fornecido como uma única sequência, com uma nova linha anexada, ao comando em sua entrada padrão (ou descritor de arquivo n se n for especificado).

wc está contando da mesma maneira, mas sua entrada é diferente.

Stephen Kitt
fonte
7
Se for necessário observar que, para imprimir o conteúdo (arbitrário) de uma variável sem um caractere de nova linha adicionado, ele deve ser printf %s "$var"(ou print -rn -- "$var"com shells semelhantes a ksh), não o printf "$var"que não funcionaria corretamente para valores $varque contenham %ou caracteres de barra invertida (ou comece com -a maioria das implementações).
Stéphane Chazelas
Observe que a implementação original da string aqui na porta Unix de rcnão adicionou esse caractere de nova linha.
Stéphane Chazelas
26

É uma nova linha subsequente adicionada pelo redirecionador here-string:

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