В продолжение постов про документацию GNU sed и спорные решения в GNU grep.
Недавно я обнаружил, что в документации на команду printf в составе GNU coreutils спецификатор %q
описан как POSIX-совместимый.
В man printf
:
%q ARGUMENT is printed in a format that can be reused as shell input,
escaping non-printable characters with the POSIX $'' syntax
В info '(coreutils) printf invocation'
:
• An additional directive ‘%q’, prints its argument string in a
format that can be reused as input by most shells. Non-printable
characters are escaped with the POSIX ‘$''’ syntax, and shell
metacharacters are quoted appropriately. This is an equivalent
format to ‘ls --quoting=shell-escape’ output.
Хотя я использую спецификатор %q
, когда пишу на bash, я впервые из этого фрагмента узнал, что $'...'
попадает под POSIX.
Я открыл довольно свежую версию SUS, и в разделе “Shell & Utilities” не нашел никакого упоминания об этом синтаксисе.
Я никогда не использую $'...'
в скриптах, в которых важна совместимость с POSIX, что, на мой взгляд, абсолютно верно.
В документации GNU coreutils, по всей видимости, содержится ошибка.
А вот что по этому поводу думает GTP-5:
Короткий ответ: да, это неточно/вводит в заблуждение. Конструкция $’…’ не является частью POSIX Shell.
Подробности:
- $’…’ — это так называемое “ANSI-C quoting” (в bash так и называется). Оно поддерживается в bash, zsh, ksh93, mksh, yash и некоторых других оболочках, но отсутствует в классическом POSIX sh (dash, большинство ash‑подобных, FreeBSD sh, OpenBSD sh и т.п.).
- В стандарте POSIX (SUS) в разделе о Shell Command Language такой синтаксис не определён. POSIX знает про ${…}, $(…), $((…)), $var, “$@”, “$*”, и т.д., но не про $’…’.
- В документации coreutils для printf %q действительно сказано: “escaping non-printable characters with the POSIX $’’ syntax”/“POSIX ‘$’‘’ syntax”. Это неверная формулировка: корректно говорить “ANSI-C $’…’ quoting”, “bash/ksh extension” или “поддерживается в большинстве современных оболочек”, но не “POSIX”.
Замечания по переносимости:
- И сам спецификатор %q в printf — расширение GNU; POSIX-овский printf его не определяет.
- Вы правы, что не используете $’…’ в строго POSIX-совместимых скриптах: такой код не будет работать в многих POSIX-оболочках (например, в dash $’a\nb’ интерпретируется не как спецквотинг, а фактически как символ ‘$’ плюс обычная одинарная строка).