Есть ли способ заставить рыбную оболочку использовать функцию printf GNU coreutils?

Возникла проблема при запуске следующей команды в оболочке fish:

❯ printf '%q\n' 'André Previn & London Symphony Orchestra'
%q: invalid conversion specification

Сначала я не осознавал, что fish на самом деле имеет свою собственную функцию printf, которая ведет себя во многом так же, как функция GNU coreutilsprintf, но не поддерживает директиву q, как GNU coreutilsprintf.

fish-shell документы:

https://fishshell.com/docs/current/cmds/printf.html#format-specifiers

GNU coreutilsprintf документы:

https://www.gnu.org/software/coreutils/manual/html_node/printf-invocation.html#printf-invocacy

Есть ли способ сообщить fish-shell, что я хочу, чтобы он использовал функцию GNU coreutilsprintf вместо настраиваемой функции printf?

[Редактировать 1]: я не осознавал, что MacOS имеет свои собственные встроенные функции, производные от BSD, которые она использует, а не встроенные функции GNU coreutils. Я по-прежнему могу использовать опцию q в zsh, но не в fish при выполнении следующих команд:

# in zsh
❯ printf '%q\n' 'test'
test

# fish, run in a zsh shell
❯ builtin printf '%q\n' 'test'
%q: invalid conversion specification

❯ command printf '%q\n' 'test'
printf: illegal format character q

50
3

Ответы:

Для этого можно использовать escape-символ

https://github.com/fish-shell/fish-shell/issues/10678#issuecomment-2303446296


Стандартная идиома, позволяющая избегать встроенных команд оболочки, — использовать env. Т.е. env printf ...


Решено

Когда вы запускаете неквалифицированный printf в fish, bash или zsh, он запускает встроенную версию printf данной оболочки.

В вашей системе есть исполняемый файл printf, вероятно, в /usr/bin/printf или аналогичном.

Чтобы запустить это, вы можете использовать command printf в рыбе или, например. env printf (что также будет работать в bash).

Однако, поскольку вы используете macOS, это не версия GNU coreutils, а собственная версия macOS, основанная на BSD.

А поскольку %q является расширением GNU, у него его не будет, и его запуск вам на самом деле не поможет.

Вы можете запустить, например. встроенный в bash printf, запустив bash:

bash -c 'printf "%q\n" "$@"' printf 'echo $(hahaha)'

(этот второй «printf» сообщает bash вызвать этот процесс «printf» — он использует его как argv0, $0)

В printf рыбы нет %q, а если бы она была, то для рыбы выполнялось бы экранирование, а не bash/zsh/sh — правила цитирования другие. Вместо этого есть string escape.