2013-03-22 4 views
7

Я немного запутался в печати переменной, содержащей новый символ строки в bash.bash printf с новой строкой

var="Age:\n20\ncolor:\nred" 
echo -e $var 
Age: 
20 
color: 
red 

Это работает, но многие люди говорят, что эхо с вариантами является not portable и it is better to use printf.

Я никогда не использовал prinf. В соответствии с руководствами для эмулирования команды эхо-сигнала:

printf '%s\n' "$var" 
Age:\n20\ncoloe:\nred 

Но это не анализирует внутреннюю переменную \ n. Инструкции, как правило, этот пример:

printf "Surname: %s\nName: %s\n" "$SURNAME" "$LASTNAME" 

Но это не мой случай, и с моей точки зрения, это не очень удобно пользоваться. Я узнал, просто набрав, что я могу использовать это:

PRINTF «$ уаг \ п»

Является ли это портативный компьютер? Если я передаю команду $ var команде mail, она сохранит новые разрывы строк?

printf "$var\n" | mail -s subj [email protected] 
+0

Проблема с 'printf' является то, что он является оболочкой встроенный в некоторых оболочках (Баш и ksh93), но внешний процесс на других (ш, ksh88, CSH) , Поэтому использование 'printf' в старых оболочках может замедлить вашу программу, в зависимости от того, сколько раз вы ее используете. – cdarke

ответ

16

printf «s %b спецификатора формата предназначались специально для замены echo -e (на самом деле, расширение XSI к echo, который требует специальной интерпретации аргументов по умолчанию. -e не указывалось и запрещен в POSIX.), и идентичен практически любым способом, включая несколько отличий от $'...' и аргумент строки формата до printf.

$ (var='Age:\n20\ncolor:\nred'; printf '%b\n' "$var") 
Age: 
20 
color: 
red 

Обычно вам следует избегать расширения переменных в строку формата, если ваша программа не контролирует точное значение, и она предназначена специально для строки формата. Ваш последний пример, в частности, может быть весьма опасным в Bash из-за printf's -v.

# Bad! 
var='-v_[$(echo "oops, arbitrary code execution" >&2)0]' 
printf "$var" foo 

Это, как правило, хорошая практика, чтобы избежать %b, если у вас есть особые требования портативность. Сохранение управляющих кодов в переменной вместо буквенных данных нарушает принципы разделения кода и данных. Есть контексты, в которых это нормально, но обычно лучше назначить значение с использованием котировки $'...', которая указана для следующей версии POSIX и уже давно доступна в Bash и большинстве вкусов ksh.

x=$'foo\nbar'; printf '%s\n' "$x" # Good 
x=(foo bar); printf '%s\n' "${x[@]}" # Also good (depending on the goal) 
x='foo\nbar'; printf '%b\n' "$x"  # Ok, especially for compatibility 
x='foo\nbar'; printf -- "$x"   # Avoid if possible, without specific reason 
+0

Благодарим вас за подробный ответ. – idobr

+0

@ormaaj: Я видел кого-то (вы?), Упоминания о функциях, которые будут добавлены к следующей версии POSIX раньше; есть ли общедоступный проект? Просто любопытно. – chepner

+0

@chepner Параметры спецификации доступны для перечисления подписчиков. 2008 TC1 уже завершен и должен быть в любое время, хотя [this] (http://austingroupbugs.net/view.php?id=249) (и другие «изменения» функции) не появятся, пока, по крайней мере, вопрос 7. Любой может читать архивы списков в [gmane] (http: //dir.gmane.org/gmane.comp.standards.posix.austin.general), или найдите трекер ошибок. Теоретически, если у вас есть нужные инструменты, вы можете сконструировать текущее состояние вещей из diff-трекера ошибок (я этого не делал). – ormaaj

Смежные вопросы