0

我有一个字符串: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""$stringprintf

4

2 回答 2

2

$"\n"查找\n当前语言环境中的翻译,但由于没有找到任何内容,所以它只是返回\n(有关详细信息,请参阅如何向 bash 脚本添加本地化支持 (BashFAQ/098))。

  1. printf %s "$string"(不需要 %s 周围的引号)获取 $string 的内容并按原样打印。

  2. printf %s""$string将 %s 与空字符串和变量的内容连接起来。\n因此进入模板并被解释为换行符。

您可以使用set -xv使 shell 向您展示它如何解释命令和变量。

从不安全的字符串创建 printf 模板是危险的。我会推荐一种不同的方式:

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

扩展为真正的$'\n'换行符,因此 $s 将包含实际的换行符。然后就可以直接打印了。

另一种方法是

printf '%s\n' $string

不改变 $string 的值。未引用的字符串会进行单词拆分,并且每个结果单词都使用添加换行符的模板打印。

于 2020-01-20T22:53:59.517 回答
0

根据 bash 手册页,您不是用换行符替换,而是用反斜杠和 n 个字符替换:

以美元符号 ($"string") 开头的双引号字符串将导致根据当前语言环境翻译该字符串。如果当前语言环境是 C 或 POSIX,则忽略美元符号。如果字符串被翻译和替换,则替换是双引号。

(我怀疑您想使用带有两个单引号的 $''。)

printf 命令将 "\n" 解释为换行符的转义序列,但仅在第一个参数中,这就是您的命令中发生的情况:

printf %s""$string
于 2020-01-20T22:58:48.157 回答