我创建了一个shell脚本,该脚本以SSH地址作为第一个参数,然后再具有一个或多个参数。该脚本可以使用两个或更少的参数(地址和单个参数),但是此后将无法正常工作。下面是我的代码,可以帮助您更好地理解。
ssh.sh $1 << EOF
$(typeset -f sr_single "$@")
if [ "$#" -eq 2 ]; then
echo $2
sr_single $2
elif [ "$#" -lt 2 ]; then
echo "Needs at least two arguments: serial number and argument(s)"
else
echo "${@:2}"
for i in "${@:2}"; do
echo "'" $i "'"
sr_single $i
done
fi
EOF
下面是我调用函数“ sr.sh test@ssh.com -l”返回的内容
-l
下面是我调用“ sr.sh test@ssh.com -l -v”时返回的内容
-l -v
' '
我的问题是,该函数如何不获取第二个变量,以及该变量之后的那个变量,该变量似乎在程序的其余部分正常工作?谢谢
答案 0 :(得分:2)
要减少脱发,请在函数中定义 all 代码,如下所示:
rmt_main() {
if (( $# == 2 )); then
printf 'Exactly arguments received; $2 is: %q\n' "$2" >&2
elif (( $# < 2 )); then
echo 'Error: Needs at least two arguments' >&2
else
otherfunc "${@:2}"
fi
}
otherfunc() {
echo "Otherfunc called with arguments:" >&2
printf '%q\n' "$@"
}
...之后,调用看起来像:
# generate an eval-safe string containing your arguments
printf -v args_str '%q ' "$@"
# explicitly invoke bash, so we don't need to worry about whether our escaping is POSIX-y
ssh "$1" 'bash -s' <<EOF
$(typeset -f rmt_main otherfunc) # emit function definitions
rmt_main $args_str # and call rmt_main with the eval-safe argument list
EOF
请注意,我们在Heredoc内部扩展的唯一内容是由本地Shell生成的,其形式保证可以正确转义以解析为代码(由远程Shell)。在任何情况下,我们都不都以非转义形式将数据(例如命令行参数)扩展到heredoc中,并且我们所有的功能均使用完全常规的引号(也就是说,全部 >引用了函数定义中的参数扩展)。