19

我对在 bash 中打印包含换行符的变量有点困惑。

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

这是可行的,但是很多人说带有选项的 echo不可移植最好使用 printf

我从来没有用过prinf。根据手册发出 echo 命令:

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

但这不会解析 \n 内部变量。手册通常有这个例子:

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

但这不是我的情况,从我的角度来看,它使用起来不舒服。我只需键入即可发现我可以使用它:

printf "$var\n"

它是便携式的吗?如果我然后将 $var 传递给邮件命令,它会保存新的换行符吗?

printf "$var\n" | mail -s subj email@domain.com 
4

1 回答 1

38

printf%b格式说明符专门用于替换(实际上,默认情况下需要对参数进行特殊解释的echo -eXSI 扩展名。从未指定过,POSIX 不允许这样做。),并且几乎在所有方面都是相同的,包括与和格式字符串参数。echo-e$'...'printf

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

您通常应该避免将变量扩展为格式字符串,除非您的程序控制了确切的值并且它专门用作格式字符串。printf由于'-v选项,您的最后一个示例在 Bash 中可能非常危险。

# 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
于 2013-03-22T08:43:55.900 回答