以这种方式尝试:
#!/bin/bash
myvals=`psql -d mydb -c "select id from table1 where 't'"`
ssh user1@host1.domain.tld "for i in $myvals; do echo \$i >> values; done"
只要psql只返回一个值,它就可以正常工作。但如果有几个值,我收到这个回复:
bash: -c: line 1: syntax error near unexpected token `2'
bash: -c: line 1: `2'
另外,我试图:
myvals='1 2 3'
然后它工作正常:值1 2 3被附加到"值"远程主机上的文件;没有错误消息。
如果我尝试另一个子shell命令,例如myvals = ls /bin
,则会再次出现错误。
很明显,$ myvals已经在本地主机上进行了评估,但是什么使得子shell结果如此不同?
答案 0 :(得分:5)
迭代一个字符串就像它是一个数组一样天生就是错误的。 Don't do it.也就是说,要生成价值的安全转义(eval
- 安全)版本,请使用printf %q
。
#!/bin/bash
myvals=`psql -d mydb -c "select id from table1 where 't'"`
printf -v myvals_q %q "$myvals"
ssh user1@host1.domain.tld \
"myvals=$myvals_q;"' for i in $myvals; do echo "$i"; done >>values'
#!/bin/bash
readarray -t myvals < <(psql -d mydb -c "select id from table1 where 't'")
printf -v myvals_q '%q ' "${myvals[@]}"
ssh user1@host1.domain.tld \
"myvals=( $myvals_q );"' for i in "${myvals[@]}"; do echo "$i"; done >>values'
#!/bin/bash
ssh user1@host1.domain.tld \
'while read -r i; do echo "$i"; done >>values' \
< <(psql -d mydb -c "select id from table1 where 't'")
echo "$i" >>values
效率低下:每次运行该行时,重新打开 values
文件。相反,在整个循环中运行重定向>values
;这会在循环开始时截断文件一次,并附加其中生成的所有值。foo='*'
,则$foo
将替换为当前目录中的文件列表,但"$foo"
将发出确切的内容 - *
。类似地,即使直接传递到echo
,也可以通过不带引号的扩展无意中损坏制表符,空白行和其他各种内容。"$foo"'$foo'
是一个字符串,其第一部分被替换为名为foo
的变量的值,而第二部分是这是完全字符串$foo
。答案 1 :(得分:0)
您可以将输出作为文件发送:
#!/bin/bash
psql -d mydb -c "select id from table1 where 't'" > /tmp/values
scp values user1@host1.domain.tld:/tmp/
或将其传送到远程主机:
psql -d mydb -c "select id from table1 where 't'" | \
ssh user1@host1.domain.tld 'while read line; do echo $line; done'