shell脚本学习指南[三](Arnold Robbins & Nelson H.F. Beebe著)

2019-09-23 09:42:11王冬梅

IFS='
  '
#另一种常见的安全性攻击,则是欺骗软件,它执行非我们所预期的命令。为了阻断
#这种攻击,我们希望调用的程序是可信任的版本,而非潜伏在用户提供的查找路径
#下的欺骗程序,因此我们将PATH设最小值,存储初始值供以后使用。exprot语句
#是这里的关键么,它可以确保所有子进程继承我们的安全查找路径。
OLDPATH="$PATH"

PATH=/bin:/usr/bin
export PATH
#错误输出函数
error(){
 echo "$@" 1>&2
 usage_and_exit 1
}
#简短的一个信息提示函数,$PROGRAM稍后会赋值为命令名
usage(){
 echo "Usage: $PROGRAM [--all] [--?] [--help] [--version] envvar pattern(s)"
}
#提供信息和状态码退出
usage_and_exit(){
 usage
 exit $1
}
#提供用户版本号
version(){
 echo "$PROGRAM version $VERSION"
}
#给出警告信息并在状态码上加1,记录警告次数
warning(){
 echo "$@" 1>&2
 EXITCODE=`expr $EXITCODE + 1`
}
#按大写全局,小写局部命名规则,初始化需要用的变量
all=no
envvar=
EXITCODE=0
#basename会截去参数最后一个斜杠之前字串,返回剩下的部分
PROGRAM=`basename $0`
VERSION=1.0
#接下来这块就是linux经典的命令行参数解析部分了,不多解释,需要注意的是?号
#是通配符,所以筛选选项的时候防止展开加上单引号。
while test $# -gt 0
do
 case $1 in
 --all | --al | --a | -all | -al | -a )
  all=yes

 --help | --hel | --he | --h | '--?' | -help | -hel | -he | -h | '-?' )
  usage_and_exit 0

 --version | --versio | --versi | --vers | --ver | --ve | --v |
 -version | -versio | -versi | -vers | -ver | -ve | -v )
  version
  exit 0

 -* )
  error "Unrecognized option: $1"

 * )
  break

#这里我小纠结了一下esac命令,没搞清楚在这干嘛的,也没这个命令说明,仔细看
#看才发现是case逆序写法,是case的结束标志,就像if结束标志fi一样
 esac
 shift
done
#下面我们要处理除选项外的参数了,我们可以用"$@"来取得,但是避免将他们存
#储在变量内如files="$@",因为文件名中如果有空格将无法正确被处理。
envvar="$1"
test $# -gt 0 && shift
#因为有可能用户提供的环境变量是PATH,为安全性考虑会重设,这是我们检测该变
#量,并适当更新envvar,开头的x是为了避免开展当成test的选项。
test "x$envvar" = "xPATH" && envvar=OLDPATH

#下边这句虽然很段,但是最棘手部分:使用shell的eval语句。我们envvar里已经拥
#有了环境变量的名称,可以"$envvar"取得,但我们现在要的是它的展开,我们也
#想要冒号分隔符转换成一般空白分隔符。如果MYPATH为用户所提供的名称,我们