向脚本传递参数-shift命令
时间:2004-12-25 来源:wingger
向脚本传递参数
前面已经讲到如何使用特定变量$ 1 . . $ 9向脚本传递参数。$ #用于统计传递参数的个数。可
以创建一个u s a g e语句,需要时可通知用户怎样以适当的调用参数调用脚本或函数。
本章内容有:
• shift。
• getopts。
• shift和g e t o p t s例子。
简单地说,下述脚本框架控制参数开始与停止。脚本需要两个参数,如果没有输入两个参数,那么产生一个u s a g e语句。注意这里使用c a s e语句处理输入脚本的不同参数。
[sam@chenwy sam]$ cat opt
#!/bin/sh
usage()
{
echo "usage:`basename $0` start|stop process name"
}
OPT=$1
PROCESSID=$2
if [ $# -ne 2 ]
then
usage
exit 1
fi
case $OPT in
start|Start) echo "Starting..$PROCESSID"
;;
stop|Stop) echo "Stopping..$PROCESSID"
;;
*)usage
;;
esac
执行脚本,输入以下参数,结果为:
[sam@chenwy sam]$ ./opt start named
Starting..named
[sam@chenwy sam]$ ./opt start named yi
usage:opt start|stop process name
[sam@chenwy sam]$ ./opt start
usage:opt start|stop process name
[sam@chenwy sam]$ ./opt start named
Starting..named
[sam@chenwy sam]$ ./opt stop named
Stopping..named
任何U N I X或L I N U X命令均接受一般格式:
命令 选项 文件
选项部分最多可包含1 2个不同的值。上述脚本中,如果必须控制不同的命令选项,就要加入大量脚本。这里只控制两个选项:开始和停止。
幸运的是s h e l l提供s h i f t命令以帮助偏移选项,使用s h i f t可以去除只使用$ 1到$ 9传递参数的限制。
1 shift命令
向脚本传递参数时,有时需要将每一个参数偏移以处理选项,这就是s h i f t命令的功能。它每次将参数位置向左偏移一位,下面用一段简单脚本详述其功能。脚本使用w h i l e循环反馈
所有传递到脚本的参数。
[sam@chenwy sam]$ cat opt2
#!/bin/sh
#loop=0
while [ $# -ne 0 ]
do echo $1
done
你可能想像,上述脚本一直执行,直到命令行中不再有更多的参数输入。错了,因为没有办法偏移到脚本中下一个参数,将只会反馈出第一个参数。执行结果如下:
[sam@chenwy sam]$ ./opt2 file1 file2 file3
file1
file1
file1
......
1.1 shift命令简单用法
使用s h i f t命令来处理传递到脚本的每一个参数。改动后脚本如下:
[sam@chenwy sam]$ cat opt2
#!/bin/sh
#loop=0
while [ $# -ne 0 ]
do echo $1
shift
done
[sam@chenwy sam]$ ./opt2 file1 file2 file3
file1
file2
file3
loop=0好像没什么用
1.2 命令行输入的最后一个参数
虽然还没有讲e v a l命令,如果需要知道命令行中输入的最后一个参数(通常是一个文件名),可以有两种选择:使用命令eval echo $$#;使用s h i f t命令:shift 'expr $# -2'。
1.3 使用shift处理文件转换
s h i f t可使控制命令行选项更加容易。下面构造一个转换脚本,使用t r将文件名转换为大写或小写。
脚本选项为:
-l 用于小写转换。
-u 用于大写转换。
使用s h i f t命令将脚本放在一起以控制- l和- u选项。脚本的第一版本如下:
[sam@chenwy sam]$ cat tr_case
#!/bin/sh
usage()
{
echo "usage: `basename $0` -[l|u] file [files]" >&2
exit 1
}
if [ $# -eq 0 ];then
usage
fi
while [ $# -gt 0 ]
do
case $1 in
-u|-U)echo "-u option specified"
shift
;;
-l|-L)echo "-l option specified"
shift
;;
*)usage
;;
esac
done
[sam@chenwy sam]$ ./tr_case
usage: tr_case -[l|u] file [files]
[sam@chenwy sam]$ ./tr_case -l
-l option specified
[sam@chenwy sam]$ ./tr_case -u
-u option specified
[sam@chenwy sam]$ ./tr_case -u -l
-u option specified
-l option specified
首先检查脚本是否有参数,如果没有,打印u s a g e语句,如果有需要处理的参数,使用c a s e语句捕获每一个传送过来的选项。当处理完此选项后,使用s h i f t命令搜集命令行中下一选项,如果未发现匹配选项,打印u s a g e语句。
[sam@chenwy sam]$ ./tr_case -u -l -k
-u option specified
-l option specified
usage: tr_case -[l|u] file [files]
下一步就是要用c a s e语句处理选项后传递过来的文件名。为此需改动c a s e语句。c a s e语句中捕获任意模式*应该为- *以允许传递无效选项,例如- p或- q。
*模式也匹配传递过来的所有文件名,以便用f o r循环处理每一个文件,这里也将使用- f选项检测文件是否存在。
改动后的c a s e语句如下:
还需要指定与选项( - l,- u)相关的变量设置。这些变量是:
T R C A S E 保存转换类型(大写或小写)。
E X T 所有文件转换后,大写文件名为. U C,小写为. L C,不保存初始文件状态。
O P T 如果给出此选项,设其为y e s,否则为n o。如果没有给出此选项,捕获此信息并反馈出来。
其他部分脚本用于实际转换处理,这里即t r命令。t r命令放在c a s e语句f o r循环中读取文件名进行处理的脚本末尾部分。
以下为完整脚本:
[sam@chenwy sam]$ cat tr_case
#!/bin/sh
FILES=""
TRCASE=""
EXT=""
OPT=no
error_msg()
{
_FILENAME=$1
echo "`basename $0`: Error the conversion failed on $_FILENAME"
}
if [ $# -eq 0 ];then
echo "for more info try `basename $0` --help"
exit 1
fi
while [ $# -gt 0 ]
do
case $1 in
-u)TRCASE=upper
EXT=".UC"
OPT=yes
shift
;;
-l)TRCASE=lower
EXT=".LC"
OPT=yes
shift
;;
-help)echo "conver a file(s) to uppercase frmo lowercase"
exit 0
;;
-*)echo "usage: `basename $0` -[l|u] file [file..]"
exit 1
;;
*)if [ -f $1 ]
then
FILES=$FILES" "$1
else
echo "`basename $0`:Error cannot file"
fi
shift
;;
esac
done
if [ "$OPT" = "no" ]
then
echo "`basename $0`:errot you need to specify an option. No acton taken"
echo "try `basename $0` --help"
exit 1
fi
for LOOP in $FILES
do
case $TRCASE in
lower) cat $LOOP|tr "[a-z]" "[A-Z]" > $LOOP$EXT
if [ $? != 0 ]
then
error_msg $LOOP
else
echo "Converted ifle called $LOOP$EXT"
fi
;;
upper) cat $LOOP|tr "[A-Z]" "[a-z]" >$LOOP$EXT
if [ $? != 0 ]
then
error_msg $LOOP
else
echo "Converterd file called $LOOP$EXT"
fi
;;
esac
done
执行上述脚本,给出不同选项,得结果如下:
只键入文件名,希望脚本提示更多帮助信息:
[sam@chenwy sam]$ ./tr_case
for more info try tr_case --help
[sam@chenwy sam]$ ./tr_case -help
conver a file(s) to uppercase frmo lowercase
[sam@chenwy sam]$ ./tr_case -et
usage: tr_case -[l|u] file [file..]
[sam@chenwy sam]$ ./tr_case -u irt
tr_case:Error cannot file
[sam@chenwy sam]$ cat case1
aaaaaaaaaaaaaaaa
[sam@chenwy sam]$ ./tr_case -l case1
Converted ifle called case1.LC
[sam@chenwy sam]$ cat case1.LC
AAAAAAAAAAAAAAAA
[sam@chenwy sam]$ cat case2
AAAAAAAAAAAA
[sam@chenwy sam]$ ./tr_case -u case2
Converterd file called case2.UC
[sam@chenwy sam]$ cat case2.UC
aaaaaaaaaaaa
使用上述脚本可以将许多文件转换为同样的格式。编写一段脚本,使其控制不同的命令行选项,这种方式编程量很大,是一件令人头疼的事。假定要写一段脚本,要求控制以下各种不同的命令行选项:
命令-l -c 23 -v 文件1文件2
s h i f t命令显得力不从心,这就需要用到g e t o p t s命令。