“shift”shell 内置命令的实际用法?

Mar*_*tin 0 shell shell-script

我检查了/usr/bin/ssh-copy-id(openssh-client至少在 Debian 下是软件包的一部分)shell-script,它包含以下 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
Run Code Online (Sandbox Code Playgroud)

shift命令的重点是什么?我的意思是我知道shift nshell 内置会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
Run Code Online (Sandbox Code Playgroud)

Gil*_*il' 8

解析-i选项后你会做什么?还有更多参数需要解析。如果-i是第一个参数,那么在处理它之后,您需要查看第三个参数。在ssh-copy-id您正在查看的旧版本中,-i是唯一选项,之后的参数是目标主机名。如果-i未传递,则目标主机名是第一个参数。

if [ "$1" = "-i" ]; then
  …
  target_host_name=$3
else
  target_host_name=$1
fi
Run Code Online (Sandbox Code Playgroud)

当有多个选项时,这不会扩展。您需要跟踪参数列表中的当前位置。

if [ "${$position}" = "-i" ]; then
  …
  position=$((position+2))
fi
target_host_name=${$position}
Run Code Online (Sandbox Code Playgroud)

问题是,我在这里写的不是有效的 shell 语法。没有简单的构造来获得第 n 个参数;你可以用 来做eval,但它很尴尬,而且古董贝壳无法处理多位参数数字。

因此,每次处理一个选项时,它都会通过调用从列表中删除shift。如果选项有参数,则调用shift 2,或shift再次调用以删除选项参数。然后在处理每个选项之后,处理的下一个参数总是$1。这样就简单多了。

if [ "$1" = "-i" ]; then
  …
  shift 2
fi
…
target_host_name=$1
Run Code Online (Sandbox Code Playgroud)