更新

更新

我创建了 shell 脚本,用于登录 FTP 服务器并重命名一些目录。我将 FTP 命令放入多行字符串中,如下所示

# !/bin/sh

ftp -inv $HOST << EOF
user $USER $PASSWORD
$COMMANDS
bye
EOF

包含$COMMANDS由换行符分隔的命令。当我像这样构造命令时,这种方法有效

NL=$'\n'
COMMANDS="command one$NL"
COMMANDS+="command two$NL"
COMMANDS+="command three"

我首先尝试$COMMANDS使用 function填充printf,但即使经过多次尝试,我也没有成功。表达方式

COMMANDS="$(printf "%s\n" "command one" "command two" "command three")"

计算为命令之间带有空格的字符串,并且当在脚本中用作 FTP 命令时,它被作为单行处理。

我尝试替换\n\r导致变量$COMMANDS未填充任何字符串。

可以有人受过更多教育吗printf向我解释一下,这里的功能有什么问题吗?

更新

我已经设法通过 rsync 实现我的目标,因此我放弃了 FTP 方法,但我仍然很好奇为什么会发生这种情况。

问题在于存储printf在变量中。我制作了测试脚本:

echo "==== printf directly"
printf "%s\n" "foo" "bar" "baz"

echo "==== stored in variable"
VAR_1=$(printf "%s\n" "foo" "bar" "baz")
echo $VAR_1

运行./test.sh输出

==== printf directly
foo
bar
baz
==== stored in variable
foo bar baz

设置IFS=$'\n'没有帮助。

更新2

如果我用双引号括起来,我可以从变量中获取多行

echo "$VAR_1"

但如果在heredoc中使用我无法得到相同的结果

echo `cat <<EOF
$VAR_1
"$VAR_1"
EOF`

我得到输出

foo bar baz "foo bar baz"

注意:heredoc中的两个变量输出之间甚至没有换行符,这对我来说也很奇怪。

答案1

当您不使用引号时,分词将在任何空格上分割字符串(默认情况下),并echo用空格连接分割部分。实际上,这将“吃掉”换行符。

您已经发现了改进之处

echo "$VAR_1"

现在对此处文档执行相同操作:

echo "`cat <<EOF
$VAR_1
EOF`"

编辑:不是echo吃换行符,而是外壳。

相关内容