首页 > 代码库 > shell 编程(四)
shell 编程(四)
上篇介绍了for循环命令的使用,本篇的shell学习,我们来看下如何在shell环境下处理用户的输入,我们可以向运行的shell从外部传入一些参数,通常情况下
$0是程序名
$1是第一个参数
$2是第二个参数
依次类推知道第9个参数$9
第9个之后需要${10}以此,至无限的
- [search@h1 812]$ cat a.sh
- echo "你输入的第一个数是: $1"
- [search@h1 812]$ sh a.sh 2
- 你输入的第一个数是: 2
- [search@h1 812]$
- [search@h1 812]$ cat a.sh
- echo "你输入的第1个数是: $1"
- echo "你输入的第2个数是: $2"
- echo "你输入的第3个数是: $3"
- [search@h1 812]$ sh a.sh 4 5 898
- 你输入的第1个数是: 4
- 你输入的第2个数是: 5
- 你输入的第3个数是: 898
- [search@h1 812]$
如果穿的是带空格的字符串,记得用双引号引起来即可。
多于10个参数的我们需要使用大括号来引用
- [search@h1 812]$ cat aa.sh
- echo "第10个参数: $10"
- echo "第11个参数: $11"
- echo "第10个参数大括号: ${10}"
- [search@h1 812]$ sh aa.sh 1 2 3 4 5 6 7 8 9 a 11 12
- 第10个参数: 10
- 第11个参数: 11
- 第10个参数大括号: a
- [search@h1 812]$
$0可以获取程序名
- [search@h1 812]$ cd
- [search@h1 ~]$ sh 812/cc.sh
- 程序名是: 812/cc.sh
- [search@h1 ~]$ cd 812/
- [search@h1 812]$ chmod u+x cc.sh
- [search@h1 812]$ ./cc.sh
- 程序名是: ./cc.sh
- [search@h1 812]$
如果只想要程序名,而不用带路径的话,可以使用basename命令来获取
- [search@h1 ~]$ cat 812/cc.sh
- echo "程序名是: $0"
- name=`basename $0`
- echo "我永远只显示程序名: $name"
- date
- [search@h1 ~]$ sh 812/cc.sh
- 程序名是: 812/cc.sh
- 我永远只显示程序名: cc.sh
- 2014年 08月 13日 星期三 03:54:57 CST
- [search@h1 ~]$
我们可以通过-n来测试参数中是否有数据:
- [search@h1 812]$ cat b.sh
- if [ -n "$1" ] ; then
- echo "有数据: $1"
- else
- echo "对不起,请输入数据: $1"
- fi
- [search@h1 812]$ sh b.sh
- 对不起,请输入数据:
- [search@h1 812]$ sh b.sh 你好
- 有数据: 你好
- [search@h1 812]$
如何知道参数总个数呢? s#命令可以满足我们
- [search@h1 812]$ cat bb.sh
- echo "你输入总个数: $#"
- [search@h1 812]$ sh bb.sh 1 2 a b cc
- 你输入总个数: 5
- [search@h1 812]$ sh bb.sh 1 2 a b
- 你输入总个数: 4
- [search@h1 812]$ sh bb.sh
- 你输入总个数: 0
- [search@h1 812]$
那么如何获取参数里面最后一个参数呢?
命令: ${!#}
- [search@h1 812]$ cat bb.sh
- echo "最后一个参数是: ${!#} "
- [search@h1 812]$ sh bb.sh
- 最后一个参数是: bb.sh
- [search@h1 812]$ sh bb.sh 2 a z
- 最后一个参数是: z
- [search@h1 812]$
如何获取所有的数据?
$*可以奖所有参数作为一个字符串显示出来
$@可以把所有参数当成一个数组来执行
- [search@h1 812]$ cat d.sh
- echo "\$* 所有的: $*"
- echo "\$@ 所有的: $@"
- #两者的区别
- for var in "$*"
- do
- echo "\$*的遍历是: $var"
- done
- echo "============================================="
- for var in "$@"
- do
- echo "\$@的遍历是: $var"
- done
- [search@h1 812]$ sh d.sh 1 2 a b 100
- $* 所有的: 1 2 a b 100
- $@ 所有的: 1 2 a b 100
- $*的遍历是: 1 2 a b 100
- =============================================
- $@的遍历是: 1
- $@的遍历是: 2
- $@的遍历是: a
- $@的遍历是: b
- $@的遍历是: 100
- [search@h1 812]$
shift命令,可以来移位参数:
- [search@h1 812]$ cat dd.sh
- echo "所有的参数是: $*"
- shift 2
- echo "移位后的参数是: $*"
- [search@h1 812]$ sh dd.sh 1 3 9 00
- 所有的参数是: 1 3 9 00
- 移位后的参数是: 9 00
- [search@h1 812]$
处理选项:
- [search@h1 812]$ cat e.sh
- while [ -n "$1" ]
- do
- case "$1" in
- -a) echo "find the -a option" ;;
- -b) echo "find the -b option" ;;
- -c) echo "find the -c option" ;;
- *) echo "$1 is not an option" ;;
- esac
- shift
- done
- [search@h1 812]$ sh e.sh -a -b -c -d
- find the -a option
- find the -b option
- find the -c option
- -d is not an option
- [search@h1 812]$ sh e.sh -a
- find the -a option
上面程序,充分利用了移位技术,来保证每个参数只会被处理一遍。
如何使选项与参数分离呢,我们可以使用--命令来做个小程序测试:
- [search@h1 812]$ cat s.sh
- while [ -n "$1" ]
- do
- case "$1" in
- -a) echo "a exist";;
- -b) echo "b exist";;
- -c) echo "c exist";;
- -d) echo "d exist";;
- --) shift
- break;;
- *) echo "$1 is not an option"
- esac
- shift
- done
- for var in "$@"
- do
- echo "剩余的参数是: $var"
- done
- [search@h1 812]$ sh s.sh -a -b -e -- 1 2 3
- a exist
- b exist
- -e is not an option
- 剩余的参数是: 1
- 剩余的参数是: 2
- 剩余的参数是: 3
- [search@h1 812]$
下面看一个getopts命令,可以帮助我们处理选项与参数的关系:
$OPTARG 保存环境变量的值 $OPTID 保存了参数列表里面的位置
如果遇到了未知的参数,会以问号代替输出
- [search@h1 812]$ cat g.sh
- while getopts :ab:c opt
- do
- case "$opt" in
- a) echo "-a exist";;
- b) echo "-b exist, with value $OPTARG";;
- c) echo "-c exist";;
- *) echo "unknow option $opt";;
- esac
- done
- [search@h1 812]$ sh g.sh -ab test1 -d
- -a exist
- -b exist, with value test1
- unknow option ?
- [search@h1 812]$
下面我们来看下如何在shell里面获取用户输入,就像我们在JAVA中使用Scanner对象获取键盘输入一样:
read命令会从键盘读入或从一个文件描述符里面读入数据,然后放进一个变量里面
- [search@h1 812]$ cat r.sh
- echo -n "请输入你的名字:"
- read name
- echo "Hello $name "
- [search@h1 812]$ sh r.sh
- 请输入你的名字:jim
- Hello jim
- [search@h1 812]$ sh r.sh
- 请输入你的名字:dongliang
- Hello dongliang
- [search@h1 812]$
我们还可以直接使用-p命令读入一行数据:
- [search@h1 812]$ cat n.sh
- read -p "请输入你的年龄:" age
- echo "你的年龄是: $age"
- [search@h1 812]$ sh n.sh
- 请输入你的年龄:23
- 你的年龄是: 23
- [search@h1 812]$ sh n.sh
- 请输入你的年龄:100
- 你的年龄是: 100
- [search@h1 812]$
你可以在read时不指定变量名,系统默认会放在$REPLY
- [search@h1 812]$ cat m.sh
- read -p "input name: "
- echo "你输入的是: $REPLY"
- [search@h1 812]$ sh m.sh
- input name: solr
- 你输入的是: solr
- [search@h1 812]$
除此之外,我们还可以对输入,设置个超时时间,如果一段时间内没人输入,就结束等待状态,程序退出!
- [search@h1 812]$ cat q.sh
- if read -t 5 -p "请在5秒内输入名字:" name
- then
- echo "你好 $name"
- else
- echo "对不起,你输入太慢了!"
- fi
- [search@h1 812]$ sh q.sh
- 请在5秒内输入名字:a
- 你好 a
- [search@h1 812]$ sh q.sh
- 请在5秒内输入名字:对不起,你输入太慢了!
- [search@h1 812]$
- [search@h1 812]$ cat w.sh
- read -n1 -p "yes or no?" var
- case $var in
- Y | y) echo "contine...";;
- N | n) echo "OK. bye bye"
- exit ;;
- esac
- echo `date`
- [search@h1 812]$ sh w.sh
- yes or no?ycontine...
- 2014年 08月 13日 星期三 05:37:10 CST
- [search@h1 812]$ sh w.sh
- yes or no?nOK. bye bye
- [search@h1 812]$ sh w.sh
- yes or no?z2014年 08月 13日 星期三 05:37:20 CST
- [search@h1 812]$
-n后面的数字1,代码可以接受几个字符,而不必按回车键
下面看下隐藏方式读取数据:
- [search@h1 812]$ cat p.sh
- read -s -p "请输入密码: " pwwd
- echo "你的密码是: $pwwd"
- [search@h1 812]$ sh p.sh
- 请输入密码: 你的密码是: abc
- [search@h1 812]$ sh p.sh
- 请输入密码: 你的密码是: hahahah
- [search@h1 812]$
最后看下如何从一个文件里面按行读取数据:
- [search@h1 812]$ cat ccc.sh
- cat abc.txt | while read line
- do
- echo "数据: $line"
- done
- echo `date`
- [search@h1 812]$ sh ccc.sh
- 数据:
- 数据:
- 数据: a
- 数据: b
- 数据: cc
- 数据: dd the
- 数据: ee
- 2014年 08月 13日 星期三 05:45:23 CST
- [search@h1 812]$ cat abc.txt
- a
- b
- cc
- dd the
- ee
- [search@h1 812]$
shell 编程(四)