printf интерпретация символов новой строки с заменой строки расширения параметра - PullRequest
0 голосов
/ 21 января 2020

У меня есть строка: string="foo=bar boo=far rab=oof raf=oob"

Я хочу заменить все пробелы в строке символом новой строки: string=${string// /$"\n"}

Когда я использую printf, bash печатает:

~$ printf "%s" "$string"
foo=bar\nboo=far\nrab=oof\nraf=oob

Однако, когда я набрал команду как printf %s""$string, я получил:

~$ printf %s""$string
foo=bar
boo=far
rab=oof
raf=oob

Какая разница в printf "%s" "$string" и printf %s""$string, что printf будет интерпретировать символы новой строки только в одной из команд?

Ответы [ 2 ]

2 голосов
/ 21 января 2020

$"\n" ищет перевод \n в текущей локали, но поскольку ничего не находит, он просто возвращает \n (см. Как добавить поддержку локализации в ваши bash скрипты (BashFAQ / 098) для деталей).

  1. printf %s "$string" (кавычки вокруг% s не нужны) берет содержимое строки $ и печатает его как есть.

  2. printf %s""$string объединяет% s с пустой строкой и содержимым переменной. \n, таким образом, попадает в шаблон и интерпретируется как новая строка.

Вы можете использовать set -xv, чтобы оболочка показывала вам, как она интерпретирует команды и переменные.

Создание шаблона printf из незащищенных строк опасно. Я бы порекомендовал другой способ:

s=${string// /$'\n'}
printf %s "$s"

$'\n' расширяется до реального символа новой строки, поэтому $ s будет содержать фактические символы новой строки. Затем вы можете распечатать его напрямую.

Другим способом было бы

printf '%s\n' $string

без изменения значения $ string. Строка без кавычек получает слово split, и каждое полученное слово печатается с использованием шаблона, который добавляет к нему новую строку.

0 голосов
/ 21 января 2020

Согласно справочной странице bash, вы НЕ заменяете символом новой строки, а вместо этого добавляете символы обратного хода sh и n символов:

Строка в двойных кавычках, перед которой стоит знак доллара ($ "string") приведет к переводу строки в соответствии с текущей локалью. Если текущая локаль C или POSIX, знак доллара игнорируется. Если строка переведена и заменена, замена заменяется двойными кавычками.

(я подозреваю, что вместо этого вы хотели использовать $ '' с двумя одинарными кавычками.)

Команда printf интерпретирует "\ n" как escape-последовательность для новой строки, но только в первом аргументе, что и происходит в вашей команде:

printf %s""$string
...