主要内容:
命令行参数
特殊参数变量
移动变量
处理选项
将选项标准化
获得用户输入
---------------
[oh@localhost shell]$ cat yh
#!/bin/bash
#using one command line parameter
factorial=1
for (( number= 1;number<=$1 ;number++))
do
factorial=$[ $factorial * $number ]
done
echo The facorial of $1 is $factorial
[oh@localhost shell]$ ./yh 5
The facorial of 5 is 120
[oh@localhost shell]$
向shell脚本传递数据
bash shell会将一些位置参数(position parameter) 的特殊变量分配给命令行输入的所有参数。
例:
./ok 2 3 4
则:
$0=程序名 ok
$1=2
$2=3
$4=4
以此类推,注意空格
[oh@localhost shell]$ cat y2
#!/bin/bash
#testing two command line parameter
total=$[ $1*$2 ]
echo the first parameter is $1
echo the second parameter is $2
[oh@localhost shell]$ ./y2 2 5
the first parameter is 2
the second parameter is 5
[oh@localhost shell]$
总之,参数是用空格隔开的。。。
[oh@localhost shell]$ cat y3
#!/bin/bash
#testing string parameters
echo $1. glad to meet you
[oh@localhost shell]$ ./y3 Michael
Michael. glad to meet you
[oh@localhost shell]$ ./y3 Michael pan
Michael. glad to meet you
[oh@localhost shell]$ ./y3 'Michael pan'
Michael pan. glad to meet you
[oh@localhost shell]$
而在参数个数多于9个时,脚本里就得变成了 ${10} ,${11}, ${12}这个样子。
[oh@localhost shell]$ cat y4
#!/bin/bash
#handling lots of parameters
total=$[ ${10}*${11} ]
echo the tenth parameter is ${10}
echo the eleventh parameter is ${11}
echo the total is $total
[oh@localhost shell]$ ./y4 1 2 3 4 5 6 7 8 9 10 11
the tenth parameter is 10
the eleventh parameter is 11
the total is 110
[oh@localhost shell]$
脚本里 echo $0 就会显示当前shell在运行的程序的名字。
[oh@localhost shell]$ cat y4
#!/bin/bash
#handling lots of parameters
total=$[ ${10}*${11} ]
echo the tenth parameter is ${10}
echo the eleventh parameter is ${11}
echo the total is $total
echo $0
[oh@localhost shell]$ ./y4 1 2 3 4 5 4 4 4 4 6 6
the tenth parameter is 6
the eleventh parameter is 6
the total is 36
./y4
但是echo $0只会显示命令的全路径:
[oh@localhost 桌面]$ echo $0
/bin/bash
[oh@localhost 桌面]$ echo $1
这显然不是我们想要得!!
于是有个命令叫basename,只返回程序名而不包括路径。
[oh@localhost 桌面]$ basename $0
bash
在脚本里,就应该是
name=`basename $0`
echo $name
[oh@localhost shell]$ cat y4
#!/bin/bash
#handling lots of parameters
#total=$[ ${10}*${11} ]
#echo the tenth parameter is ${10}
#echo the eleventh parameter is ${11}
echo the total is `basename $0`
[oh@localhost shell]$ cat y5
#!/bin/bash
# testing a multi-function script
name=`basename $0`
if [ $name="yy" ]
then
total=$[ $1*$2 ]
elif [ $name='y5' ]
then
total=$[ $1+$2 ]
fi
echo the total is $total
[oh@localhost shell]$ ./y5 2 4
the total is 8
[oh@localhost shell]$
-----
当脚本需要一个参数而你没给时,可能会出问题。
[oh@localhost shell]$ cat yh
#!/bin/bash
#using one command line parameter
factorial=1
for (( number= 1;number<=$1 ;number++))
do
factorial=$[ $factorial * $number ]
done
echo The facorial of $1 is $factorial
[oh@localhost shell]$ ./yh 2
The facorial of 2 is 2
[oh@localhost shell]$ ./yh
./yh: line 5: ((: number<= : syntax error: operand expected (error token is "<= ")
The facorial of is 1
[oh@localhost shell]$
所以,最好先判断一下是否有数据传入。
if [ -n "$1" ]
[oh@localhost shell]$ cat y6
#!/bin/bash
#testing parameter befor use
if [ -n "$1" ]
then
echo hello $1 ,nice to meet you
else
echo "sorry ,you did not identify yourself"
fi
[oh@localhost shell]$ ./y6 boo
hello boo ,nice to meet you
[oh@localhost shell]$ ./y6
sorry ,you did not identify yourself
[oh@localhost shell]$
------
$#可以查看命令行里输入了多少个参数
echo $#
[oh@localhost 桌面]$ echo $#
0
[oh@localhost shell]$ cat ya
#!/bin/bash
#getting number of parameters
echo there is $# parameters supplied
[oh@localhost shell]$ ./ya 2 3 4 5 6
there is 5 parameters supplied
[oh@localhost shell]$
[oh@localhost shell]$
[oh@localhost shell]$ vim ya
[oh@localhost shell]$ cat ya
#!/bin/bash
#getting number of parameters
echo there is $# parameters supplied
echo the last parameter is ${$#}
[oh@localhost shell]$ ./ya 1 2 3 4 5
there is 5 parameters supplied
the last parameter is 6995
[oh@localhost shell]$
[oh@localhost shell]$
[oh@localhost shell]$ vim ya
[oh@localhost shell]$ cat ya
#!/bin/bash
#getting number of parameters
echo there is $# parameters supplied
echo the last parameter is ${!#}
[oh@localhost shell]$ ./ya 1 2 3 4 5
there is 5 parameters supplied
the last parameter is 5
[oh@localhost shell]$
既然是个数,那么是不是说${$#}可以得到最后的哪个参数呢,结果不是的。不行。
因为在{}里,不能使用$
你得${!#},是的,把$改成!就可以了。
当你需要遍历所有的参数时,可以使用$* 于 $@ 加上for循环来解决这些问题。
[oh@localhost shell]$ cat yb
#!/bin/bash
#testing $* and $@
count=1
for param in "$*"
do
echo "\$* parameter #$count=$param"
count=$[ $count+1 ]
done
count=1
for param in "$@"
do
echo "\$@ parameter #$count=$param"
count=$[ $count+1 ]
done
[oh@localhost shell]$ ./yb ad cd vd fd ed
$* parameter #1=ad cd vd fd ed
$@ parameter #1=ad
$@ parameter #2=cd
$@ parameter #3=vd
$@ parameter #4=fd
$@ parameter #5=ed
[oh@localhost shell]$
$*是将整个参数列单作一个字符串,不再可分割。而$@是将当作多个单词,允许你遍历地访问它,有点像数组。
-----------
移动变量,shift 命令,在使用shift命令时,默认情况下它会将每个参数的位置减一。
[oh@localhost shell]$ cat yc
#!/bin/bash
#demonstrating the shift command
count=1
while [ -n "$1" ]
do
echo "parameter #$count=$1"
count=$[ $count+1 ]
shift 2
done
[oh@localhost shell]$ ./yc ad dd fd ed sd ee
parameter #1=ad
parameter #2=fd
parameter #3=sd
[oh@localhost shell]$
如,$3的值会移到$2,$2-----$1,$1没有被移到$0,而是被丢掉了,$0是程序的名字,不会被改变。
-------------
ok,现在你想加一些选项 options
1.处理简单选项
可使用case语句
[oh@localhost shell]$ cat yd
#!/bin/bash
#extracting command line ooptions as parameter
while [ -n "$1" ]
do
case "$1" in
-a) echo "oh -a option" ;;
-b) echo "oh -b option" ;;
-c) echo "oh -c option" ;;
esac
shift 1
done
[oh@localhost shell]$ ./yd -a -b -c -d
oh -a option
oh -b option
oh -c option
[oh@localhost shell]$
2.分离参数和选项
现在这里既有参数,又有选项,那么怎么分辨是要参数还是要选项呢???
linux 有个特殊的字符 -- 用它来表明选项结束了。那么它后面的东西就是参数了。
[oh@localhost shell]$ cat ye
#!/bin/bash
#extracting command line ooptions as parameter
while [ -n "$1" ]
do
case "$1" in
-a) echo "oh -a option" ;;
-b) echo "oh -b option" ;;
-c) echo "oh -c option" ;;
--) shift
break ;;
*) echo "$1 is not an option"
esac
shift 1
done
count=1
for param in $@
do
echo "parameter #$count: $param"
count=$[ $count+1 ]
done
[oh@localhost shell]$ ./ye -a -b -c test test2 test3
oh -a option
oh -b option
oh -c option
test is not an option
test2 is not an option
test3 is not an option
[oh@localhost shell]$
[oh@localhost shell]$ ./ye -a -b -c -- test test2 test3
oh -a option
oh -b option
oh -c option
parameter #1: test
parameter #2: test2
parameter #3: test3
[oh@localhost shell]$
3.处理带值的选项
hi -a 34 -b 3
这就叫带值的参数了。
[oh@localhost shell]$ cat yf
#!/bin/bash
#extracting command line ooptions as parameter
while [ -n "$1" ]
do
case "$1" in
-a) echo "oh -a option" ;;
-b) echo "oh -b option ,with a parameter value $2"
shift 2;;
-c) echo "oh -c option" ;;
--) shift
break ;;
*) echo "$1 is not an option"
esac
shift 1
done
count=1
for param in $@
do
echo "parameter #$count: $param"
count=$[ $count+1 ]
done
[oh@localhost shell]$ ./yf -a -b ert -c -d
oh -a option
oh -b option ,with a parameter value ert
-d is not an option
[oh@localhost shell]$
但是以上的方式都不能处理选项的合并这种情况。
hi -ac
[oh@localhost shell]$ ./yf -ab
-ab is not an option
[oh@localhost shell]$
====
getopt 命令是一个处理命令行选项和参数非常方便的工具。
它的格式是 getopt options optstring parameters
optstring 是这个过程的关键所在,它定义了命令行有效的选项字母,还定义了哪些选项字母需要参数。
如果选项是有带参数的,那么在它后面加:号
然后getopt会将命令转换成合适的格式。
getopt ab:cd -a -b test1 -cd test2 test3
----------> -a -b test1 -c -d -- test2 test3
因为ab后面有冒号,所以它是有跟一个值的
是的,--符号是自动加的,而如果你指定了一个不在optstrings中的选项,默认是会产生错误的。
但是可以加个-q选项来忽略错误消息
然后-q会把 错误的选项扔掉
[oh@localhost shell]$ getopt ag:c -a -b -c tile -g tilee
getopt: invalid option -- 'b'
-a -c -g tilee -- tile
[oh@localhost shell]$ getopt -q ag:c -a -b -c tile -g tilee
-a -c -g 'tilee' -- 'tile'
[oh@localhost shell]$ getopt -q age:c -a -b -c tile -ge tilee ttt
-a -c -g -e 'tilee' -- 'tile' 'ttt'
[oh@localhost shell]$
[oh@localhost shell]$ getopt ag:c -a -b -c tile -g tilee
getopt: invalid option -- 'b'
-a -c -g tilee -- tile
[oh@localhost shell]$ getopt -q ag:c -a -b -c tile -g tilee
-a -c -g 'tilee' -- 'tile'
[oh@localhost shell]$ getopt -q age:c -a -b -c tile -ge tilee ttt
-a -c -g -e 'tilee' -- 'tile' 'ttt'
[oh@localhost shell]$
[oh@localhost shell]$ vim yg
[oh@localhost shell]$ cat yg
#!/bin/bash
# extracting command line options and values with getopt
set -- `getopt -q ab:c "$@" `
while [ -n "$1" ]
do
case "$1" in
-a) echo "found the -a option";;
-b) param="$2"
echo "found the -b option with parameter value $param"
shift ;;
-c) echo "found the -c option";;
--)shift
break ;;
*) echo "$1 is not an option";;
esac
shift
done
count=1
for param in "$@"
do
echo "parameter #$count: $param"
count=$[ $count+1 ]
done
[oh@localhost shell]$ ./yg -ac
found the -a option
found the -c option
[oh@localhost shell]$
----------
现在来考虑如何在脚本中使用getopt了
大概是这样子:
set -- `getopts -q ab:cd "$@"`
set命令的选项之一是双破折线,他会将命令行参数替换成set命令的命令行的值。
[oh@localhost shell]$ ./yg -a -b test -cd test2 test3 test4
found the -a option
found the -b option with parameter value 'test'
found the -c option
parameter #1: 'test2'
parameter #2: 'test3'
parameter #3: 'test4'
然后,该方法会将原始的脚本的命令行参数传给getopt命令,之后再将getopt命令的输出传给set命令,用getopt格式化后的命令行参数来替换原始的命令行参数。
但是,getopt有个致命的问题。不善常处理带空格的参数。他会将空格当作参数分隔符,而不是根据引号将二者当作一个参数。
[oh@localhost shell]$ ./yg -a -b test1 -cd "rdd ddt" test4
found the -a option
found the -b option with parameter value 'test1'
found the -c option
parameter #1: 'rdd
parameter #2: ddt'
parameter #3: 'test4'
[oh@localhost shell]$
于是有个叫getopts的命令要出现了,他是getopt的升级版。
----------不想写了,下次来。。。。
好吧好吧,该来的总归回来的!!!
其实还是要实战啊,才能真正了解问题。
[oh@localhost shell]$ cat yj
#!/bin/bash
#simple demostration of the getopts command
while getopts :ab:c opt
do case "$opt" in
a) echo "found the -a option";;
b) echo "found the -b option. with value $OPTARG";;
c) echo "found the -c option" ;;
*) "unknow option :$opt";;
esac
done
[oh@localhost shell]$ ./yj -ab teeeee -c
found the -a option
found the -b option. with value teeeee
found the -c option
[oh@localhost shell]$
可以看到,不用单破则号!!!!
bash shell 包含了 getopts命令,与getopt将命令行上找到的选项和参数处理后生成一个输出不同,getopts命令能够和已有的shell参数变量对应的顺序工作。 处理完所有参数后,退出,并返回一个大于0的退出状态码。适合在循环中。
格式如下:getopts optstring variable
要去掉错误消息的话,可以在optstring的前面加一个:
getopts会用到两个环境变量: OPTARG,OPTIND
OPTARG:保存选项的参数值
OPTIND:getopts正在处理的参数位置
[oh@localhost shell]$ ./yj -a eee -b "ok jj"
found the -a option
[oh@localhost shell]$ ./yj -b "ok jj" -a
found the -b option. with value ok jj
found the -a option
[oh@localhost shell]$ ./yj -a -b "ok jj"
found the -a option
found the -b option. with value ok jj
[oh@localhost shell]$ ^C
[oh@localhost shell]$ vim yj
[oh@localhost shell]$ ./yj -a eee -b "ok jj"
found the -a option
found the -b option. with value ok jj
[oh@localhost shell]$ cat yj
#!/bin/bash
#simple demostration of the getopts command
while getopts :a:b:c opt
do case "$opt" in
a) echo "found the -a option";;
b) echo "found the -b option. with value $OPTARG";;
c) echo "found the -c option" ;;
*) "unknow option :$opt";;
esac
done
[oh@localhost shell]$
使用 OPTIND 和 shift 一起移动参数
[oh@localhost shell]$ ./yk -a -b test -d tes ee dd dddd
found the -a option
found the -b option. with value test
./yk: line 9: unknow option :?: command not found
parmeter 1: dd
parmeter 2: dddd
[oh@localhost shell]$ cat yk
#!/bin/bash
#simple demostration of the getopts command
while getopts :ab:c opt
do case "$opt" in
a) echo "found the -a option";;
b) echo "found the -b option. with value $OPTARG";;
c) echo "found the -c option" ;;
*) "unknow option :$opt";;
esac
done
shift $[ $OPTIND+1 ]
count=1
for param in "$@"
do
echo "parmeter $count: $param"
count=$[ $count+1 ]
done
[oh@localhost shell]$
[oh@localhost shell]$ cat yk
#!/bin/bash
#simple demostration of the getopts command
while getopts :ab:cd opt
do case "$opt" in
a) echo "found the -a option";;
b) echo "found the -b option. with value $OPTARG";;
c) echo "found the -c option" ;;
d) echo "found the -d option" ;;
*) "unknow option :$opt";;
esac
done
shift $[ $OPTIND+1 ]
count=1
for param in "$@"
do
echo "parmeter $count: $param"
count=$[ $count+1 ]
done
[oh@localhost shell]$ ./yk -a -b test -d tes ee dd dddd
found the -a option
found the -b option. with value test
found the -d option
parmeter 1: dd
parmeter 2: dddd
[oh@localhost shell]$
==========
将选项标准化:
-a:显示所有对象
-c:............
.........
.........
类似这样。。。
====================
或得用户输入:
好了,现在你想在脚本运行的时候获取一些变量,或是许可,
哪么,你得知道read命令!!
read从标准输入(键盘)或另一个文件描述符得到输入。
read adc
read -p "please enter somethings" thing
read -p "ok,ok," thing ohhh //读了两个数
read -p "no name"
对于最后一个当没有变量名时,系统会将得到的数据存入 特殊的环境变量 REPLY 里。
对于超时问题, read -t 选项来指定一个计时器,等待秒数,当计时器过期后,read会返回一个非零退出状态码。
配合着if - then语句使用。
if read -t 5 -p "please enter your name : " name
不想将输入显示在屏幕上,哪个叫隐含输入 read -s
====
从文件里读取数据,每次读取一行
cat test | while read line
do
$line
done