Как echo
и printf
лечить слеш zsh
, bash
и другие снаряды?
Под Zsh я получаю следующее поведение:
$ echo "foo\bar\baz"
foaaz
$ echo "foo\\bar\\baz"
foaaz
$ echo 'foo\bar\baz'
foaaz
$ echo 'foo\\bar\\baz'
foo\bar\baz
В bash все выглядит более согласованным:
bash$ echo "foo\bar\baz"
foo\bar\baz
bash$ echo 'foo\bar\baz'
foo\bar\baz
bash$
Но более конкретно: как я могу передать строку, содержащую обратную косую черту, такую как\\foo\bar\something
:
echo
printf
print
и получить точно такую же строку? (в zsh
а bash
)?
Вот еще один эксперимент с функциями в Zsh:
function foo
{
echo -E '$1'
}
$ foo \\here\is\some\path
$1
Как я могу это просто напечатать \\here\is\some\path
?
Обновление (Примечание: на этот вопрос уже дан ответ в комментарии Стефана)
Я пробовал следующее в zsh 5.0.2:
function foo
{
printf '$s\n' $1
}
foo '\\some\path'
Но это печатает $s
?
printf
,echo
не переносимо в этом отношении.'
на"
и вызываете ее с помощью: foo '\\ here \ is \ some \ path' (в противном случае вызывающая оболочка получает возможность интерпретировать '\' до того, как они попадут в функцию)'$s\n'
когда она должна была использоваться'%s\n'
.Ответы:
zsh
echo
ведет себя стандартным образом, какbash
в режиме UNIX. То есть он расширяется\b
до символа ASCII BS, как того требует спецификация UNIX.Не используйте
echo
для отображения произвольных строк, используйтеprintf
:print -r -- "$1"
также работает, но являетсяksh
/zsh
конкретным.echo -E - "$1"
работать сzsh
и я считаю, что некоторые BSD.работает в любой оболочке, похожей на Bourne, даже в те несколько десятилетий, когда не было
printf
команды, но она порождала новый процесс, и в настоящее время это действительно не нужно, как сейчас у насprintf
везде.И, кстати, вам нужно избегать обратной косой черты в командной строке оболочки, так как она особенная для оболочки (каждая оболочка, кроме
rc
), поэтому:foo \\foo\bar
передаст"\foo\bar"
строку, вfoo
которую не сможет заново создать потерянный обратный слеш.источник
printf '%s\n' "$var"
работает для меня в командной строке (zsh 5.0.2
т.е. в самой последней), но не внутри функции (см. Мое обновление в ОП). Почему?printf '%s\n'
неprintf '$s\n'
ты хочешь. Обратите внимание, что вам нужно заключать переменные в другие оболочки, отличные отzsh
("$1"
, не$1
), и стандартный синтаксис определения функцииfoo() { ...; }
, хотя любая оболочка, ноbash
позволяетfoo() any-command
, иfunction foo { .... }
являетсяksh
синтаксисом.новый ответ: прочитайте -r var
и отобразить:
должно сработать.
Итак, для вашей функции foo:
старый ответ ниже (не отвечает, но может быть полезным ^^)
просто замените каждый
\
на,\\
чтобы сказать оболочке «что это буквально все, что\
я хочу». в противном случае (например, в zsh, в вашем примере) вполне может быть, что\b
означает «1 возврат» или что-то еще.Вы можете, например, использовать sed:
(посмотрите, как вам также нужно убежать "\" там, чтобы сказать sed то же самое: "это буквально" \ "Я хочу) (и обратите внимание, что я окружаю его символом '', а не" ", чтобы избежать интерпретации оболочки большинство тоже)
источник
read -r var
кажется, ждать ввода отSTDIN
. Что если я передам это в качестве аргумента? (например, foo\\here\is\some\path
)Вообще говоря, вы не можете, потому что обратная косая черта является escape-символом (и поэтому должна быть экранирована, когда требуется ее буквальное значение). BASH предоставляет одинарные кавычки для этой цели, однако вы не можете использовать экранирование одинарных кавычек в одинарных кавычках.
Что касается
echo
несоответствия, то это встроенная функция может вести себя по-разному в различных оболочках (в некоторой степени). Например, встроенная функция BASH имеет-e
опцию, которая указывает ей интерпретировать последовательности обратной косой черты - с ее помощью вы получите поведение, которое вы видели в оболочке Z.источник