Почему оболочка printf запускает строки вместе, когда не заключена в кавычки? - PullRequest
1 голос
/ 10 июня 2019

Может кто-нибудь объяснить это поведение в сценарии оболочки:

TESTVAR='something fishy'
echo $TESTVAR
something fishy

Но

printf "%b" $TESTVAR
somethingfishy            (space removed)

Пока

printf "%b" "$TESTVAR"
something fishy

Почему это так?

1 Ответ

3 голосов
/ 10 июня 2019

Это поведение является следствием двух правил:

  • Когда вы передаете printf больше аргументов, чем строка формата содержит заполнители, строка формата повторяется до тех пор, пока не будут использованы все аргументы. С форматной строкой, имеющей только один заполнитель, это означает, что она повторяется один раз для каждого последующего аргумента.

  • Когда вы не заключаете в кавычки расширения параметров, они подвергаются разделению слов (создание отдельного слова для содержимого по обе стороны от каждого символа в IFS) и расширению глобуса (заменяя эти слова списком имен файлов). которым они соответствуют, когда интерпретируются как globs, если такие имена существуют), что приводит к переменному числу слов оболочки, каждое из которых передается в качестве отдельного аргумента printf.


Таким образом, TESTVAR='something fishy'; echo $TESTVAR со значением по умолчанию IFS становится точным эквивалентом echo "something" "fishy", который печатает something fishy, поскольку echo разделяет каждый аргумент пробелом.

Напротив, printf %b $TESTVAR становится printf %b "something" "fishy", который использует %b для форматирования something, и снова для форматирования fishy; ничего там не вставляет пробел, поэтому вы не получите пробелов на выходе. (Если бы вместо этого вы сделали printf '%b ' $TESTVAR, вы бы увидели вставленные пробелы).

Наконец, printf %b "$TESTVAR" работает printf %b "something fishy"; пробел сохраняется, поскольку он является литеральной частью третьего аргумента, поэтому строка формата %b оценивается только один раз по отношению ко всему аргументу something fishy с уже включенным пробелом.


Урок этой истории: Всегда цитируйте свои расширения. См. Также BashPitfalls # 14 , подробно описывающий, как echo $foo сам по себе глючит, если не указан echo "$foo".

...