【问题标题】:BASH Script passing variable with space to Heredoc?BASH脚本将带有空格的变量传递给Heredoc?
【发布时间】:2020-11-02 16:13:55
【问题描述】:

我正在使用以下内容:

filename="Test File 17-07-2020.xls"

sshpass -p $password ssh root@$IP /bin/bash -s "$filename" << 'EOF'

echo $1

EOF

这在文件名等于 Testfile.xls 并且 echo 输出完整文件名时有效。

但是如果文件名被称为Test File 17-07-2020.xls则失败

我的理解是空格会破坏输入,所以它变成:

$1 = Test
$2 = File
$3 = 17-07-2020.xls

有没有办法通过这个保留空格并将其全部保存在$1

如果我在 SSHPASS 命令之前添加filename=$(echo "$filename" | sed 's/ /\\ /g'),它确实有效。

这是一种有效的方法还是有更好的方法?

谢谢

【问题讨论】:

  • echo "$1" 显示 'Test' 不是全名。
  • 在不需要第二个参数的情况下,您可以使用"$*" 代替$1,但它不是一个非常强大的解决方案。

标签: bash heredoc


【解决方案1】:

您仍然需要引用$1。引用分隔符可防止$1 过早扩展;一旦shell实际执行echo $1,它就不会阻止分词。

sshpass -p $password ssh root@$IP "/bin/bash -s \"$filename\"" << 'EOF'

echo "$1"

EOF

如果您在本地使用 bash,则有两个扩展可以生成可以安全地传递给远程 shell 的值。

sshpass -p $password ssh root@$IP "/bin/bash -s $(printf '%q' "$filename")"

sshpass -p $password ssh root@$IP "/bin/bash -s ${filename@Q}"

前者至少在bash 3.2 中工作(我非常怀疑你使用的是旧版本),而后者需要bash 4.4。

【讨论】:

  • 我找到了这个,但是如果文件名有没有斜杠的空格,那么 $1 只包含 Test。
  • 哦,对了,因为整组参数被ssh 打包成一个单词传递给远程shell。我已经修复了它来处理您的情况,但这仍然不够稳健:如果 $filename 本身包含双引号,它将失败。
  • 您可以将内部双引号换成单引号 ("/bin/bash -s '$filename'"),但这只会将问题转移到包含单引号的文件名上。
  • ${filename@Q} 怎么样?
  • 是的,我只是在玩这个。 printf '%q' "$filename""${filename@Q}" 产生不同的输出,所以我试图说服自己两者都行。 (我可能倾向于 print "%q" ...,因为它更有可能得到支持;@Q 需要 bash 4.4 或更高版本。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-12-13
  • 1970-01-01
  • 2015-10-21
相关资源
最近更新 更多