Почему wc <<< «$ string» показывает длину в один байт больше, чем printf «$ string» | Туалет?

11

Случайно я обнаружил, что wcзначение по-разному зависит от того, как он получает информацию от bash:

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

Это - ИМХО сбивает с толку - поведение где-то задокументировано? Что wcздесь значить - это предполагаемый перевод строки?

rexkogitans
источник
3
Вы всегда можете od -cпосмотреть, что именно у вас есть.
Торбьерн Равн Андерсен
Или лучше xxd -g1.
Руслан
1
Надеюсь, printf "$s"это не ваш настоящий сценарий ... надеюсь, вы имели в видуprintf "%s" "$s"
user541686
Поскольку было очень много комментариев о printf, я отредактировал свой пост, чтобы отразить лучшие практики.
rexkogitans

Ответы:

38

Разница вызвана новой строкой, добавленной к строке here. Смотрите руководство по Bash :

Результат передается в виде одной строки с добавленной новой строкой к команде на ее стандартном вводе (или дескриптору файла n, если указано n ).

wc рассчитывает таким же образом, но его ввод отличается.

Стивен Китт
источник
7
Если следует отметить, что для печати (произвольного) содержимого переменной без добавления символа новой строки, это должно быть printf %s "$var"(или print -rn -- "$var"с ksh-подобными оболочками), что не printf "$var"будет работать правильно для значений, $varкоторые содержат %символы или символы обратной косой черты (или начать с -большинства реализаций).
Стефан Шазелас
Обратите внимание, что оригинальная реализация здесь-строки в порту Unix rcне добавила этот символ новой строки.
Стефан Шазелас
26

Это следующий перевод строки, добавленный перенаправителем 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
Мерфи
источник