我检查了shell 脚本/usr/bin/ssh-copy-id
(openssh-client
至少在 Debian 下是包的一部分),它包含以下 if 语句:
if [ "-i" = "$1" ]; then
shift
# check if we have 2 parameters left, if so the first is the new ID file
if [ -n "$2" ]; then
if expr "$1" : ".*\.pub" > /dev/null ; then
ID_FILE="$1"
else
ID_FILE="$1.pub"
fi
shift # and this should leave $1 as the target name
fi
else
命令的要点是什么shift
?我的意思是我知道shift n
shell 内置函数将n
参数数量从左向右移动,但是在此脚本中使用它的原因是什么?为什么不使用:
if [ "-i" = "$1" ]; then
if [ -n "$3" ]; then
if expr "$2" : ".*\.pub" > /dev/null ; then
ID_FILE="$2"
else
ID_FILE="$2.pub"
fi
fi
答案1
解析完-i
选项后你会做什么?还有更多参数需要解析。如果-i
是第一个参数,那么在处理完它之后,您需要查看第三个参数。在ssh-copy-id
您正在查看的旧版本中,-i
是唯一的选项,后面的参数是目标主机名。如果-i
未传递,则目标主机名是第一个参数。
if [ "$1" = "-i" ]; then
…
target_host_name=$3
else
target_host_name=$1
fi
当有多个选项时,这不会扩展。您需要跟踪参数列表中的当前位置。
if [ "${$position}" = "-i" ]; then
…
position=$((position+2))
fi
target_host_name=${$position}
问题是,我在这里写的不是有效的 shell 语法。没有简单的构造来获取第 n 个参数;你可以用 来做到这一点eval
,但这很尴尬,而且古董 shell 无法处理多位参数数字。
因此,每次处理选项时,都会通过调用 来将其从列表中删除shift
。如果选项有参数,请调用shift 2
或shift
再次调用以删除选项参数。然后,在处理每个选项之后,处理的下一个参数始终是$1
。这样就更简单了。
if [ "$1" = "-i" ]; then
…
shift 2
fi
…
target_host_name=$1