处理用户输入

主要内容:

命令行参数

特殊参数变量

移动变量

处理选项

将选项标准化

获得用户输入

---------------

[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


































  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值