我创建了 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
吃换行符,而是外壳。