《Linux命令行与shell脚本编程大全》第十四章 处理用户输入
有时还会需要脚本能够与使用者交互。bash shell提供了一些不同的方法来从用户处获得数据,
包括命令行参数,命令行选项,以及直接从键盘读取输入的能力。
14.1 命令行参数
就是添加在命令后的数据
比如: ./addem 10 30
10 和 30 就是传递的命令行参数
14.1.1 读取参数
bash shell会将一些称为位置参数的特殊变量分配给输入到命令行中的所有参数。
比如: $0:程序名 $1:第一个参数 $2:第2个参数 …… 以此类推直到第九个参数。
每个参数都必须用空格分开。可以使用数字也可以使用文本。如果文本有空格,需要用引号括起来,(单引号双引号均可)
若参数不止9个,第十个以后的需要加花括号处理。比如${10}:第十个参数 ${11}:第11个参数。这样就可以添加任意多的参数了。
14.1.2 读取脚本名
$0 参数获取shell在命令行启动的脚本名。
也就是说 同一个脚本test。 ./test 运行 和 /xcy/home/test 这样会得到不同的结果。
basename会返回不包含路径的脚本名。比如 name=$(basename $0)
例子:
1 #!/bin/bash
2 # canshu test
3 echo "Command Name is $0"
4 name=$(basename $0)
5 echo "file name is $name"
6 echo "Hi, My name is $1, I am $2, I am come from $3"
7 echo "Param4: $4, Param5:$5 ...... Param10:${10}, Param11:${11}"
运行:
14.1.3 测试参数
如果脚本中使用了命令行参数,脚本不加参数运行可能会出问题。
可以先判断参数是否存在。使用前此案检查是否存在数据
使用 –n 来检查命令行参数是否有数据。
例子:
1 #/bin/bash
2 # check param
3 if [ -n "$1" ] # 需要用双引号括起来
4 then
5 echo "hello, $1, nice to meet you"
6 else
7 echo "sorry, you are illegality"
8 fi
运行:可以这样
./test2
./test2 xiaochongyong
14.2 特殊参数变量
14.2.1 参数统计
$# 可以统计参数个数,统计输入了多少个参数
假如有5个参数,那么 $# 会是5。 那么${$#}就应该是最后一个参数。然而其实并不是这样。
其实不能在花括号里面是有美元符。必须换成感叹号。${!#}
14.2.2 抓取所有的变量
抓取命令行上提供的所有参数。
$* 和 $@ 变量可以用来访问所有的参数。
$*:将命令行上提供的所有参数当做一个单词保存,可以看做一个整体
$@:将命令行上提供的所有参数当做同一字符串中的多个独立的单词。可以用for遍历所有的参数值。
例子: 这里的反斜杠是为了转义美元符
1 #!/bin/bash
2 # test
3 echo "Param count:$#"
4 echo "Last Param:${!#}"
5 echo "param \$*:$*"
6 echo "param \$@:$@"
7 count=1
8 for param in "$*" # for param in $*, no ""。如果没有双引号,效果一样
9 do
10 echo " Param \$* #$count = $param"
11 count=$[ $count + 1 ]
12 done
13
14 count=1
15 for param1 in "$@"
16 do
17 echo " Param \$@ #$count = $param1"
18 count=$[ $count + 1 ]
19 done
运行:./test 1 2 3 4 5
注意第10行和第17行的输出的区别
14.3 移动变量
bash shell的shift工具命令能操作命令行参数。
shift命令会根据它们的相对位置来移动命令行参数。
如何使用:默认情况下将每个参数变量向左移动一个位置。
$3移动到$2, $2移动到$1。$1的值就被丢弃了,$0的值不会被改变。
1 #!/bin/bash
2 # shift test
3 count=1
4 while [ -n "$1" ]
5 do
6 echo "Param$count = $1"
7 count=$[ $count + 1 ] # 这个是数学运算
8 shift
9 done
运行: ./test 1 2 3 4 5 6 7
还可以一次性移动多个, shift n n表示移动位置数
14.4 处理选项
选项:跟在单破折线后面的单个字母,它能改变命令的行为。比如 ls -a
14.4.1 查找选项
1.处理简单选项。
比如下面的例子:
1 #!/bin/bash
2
3 if [ -n "$1" ]
4 then
5 case "$1" in
6 -a) echo "this is -a option";;
7 -b) echo "this is -b option";;
8 -c) echo "this is -c option";;
9 -d) echo "this is -d option";;
10 esac
11 else
12 echo "no param"
13 fi
运行:
./test -a
./test –b
2. 分离参数和选项
如果需要在shell脚本中同时使用选项和参数。
解决方案是用特殊字符来将二者分开。
shell会用双破折线来表明选项列表结束。在双破破折现之后脚本就可以放心的将剩下的命令当做参数了。而不是选项
运行脚本时, -- 之前的是选项和选项的参数。 -- 的之后就是命令行参数。
3. 处理带值的参数
有时候选项会带上一个额外的参数值。
由于要处理的选项是$1 ,那么参数就在它后面,就是$2.
例子:
1 #!/bin/bash
2 echo
3 while [ -n "$1" ]
4 do
5 case "$1" in
6 -a) echo "Found the -a option";;
7 -b) value=$2 # 这里处理选项参数
8 echo "Found the -b option, Param = $value"
9 shift;;
10 -c) echo "Found the -c option";;
11 --) shift
12 break;;
13 *) echo "$1 is not option";;
14 esac
15 shift
16 done
17 # 上面处理选项,下面是处理命令行参数
18 count=1
19 for param in $@
20 do
21 echo "Param$count = $param"
22 count=$[ $count + 1 ]
23 done
运行:
14.4.2 使用getopt命令
它能够识别命令行参数,从而在脚本中解析它们。
1.命令的格式
可以接受一系列任意形式的命令行选项和参数,并自动将它们转换成命令行参数。
命令格式如下:
getopt optstring parameters
optstring:定义了命令行有效的选项字母,还定义了哪些选项字母需要参数值
比如:
$getopt ab:cd –a –b testb –cd test2 test3
b后面接了冒号:说明-b选项需要参数。
后面 –cd 会被自动拆分成 –c -d 两个单独的选项
还会插入双破折线来分割行中的额外参数。
2.在脚本中使用getopt
可以在脚本中使用getopt来格式化脚本所携带的任何命令行选项或者参数,用起来略繁琐。
方法是:用getopt命令生成的格式化后的版本来替换已有的命令行参数和选项。
用set命令可以做到。需要的选项之一就是 双破折号 --。它会将命令行参数替换成set命令的命令行值。
但是这个不擅长处理带空格和带引号的参数值,它会将空格当做参数分隔符,而不是根据双引号将二者当做一个参数
例子:
1 #!/bin/bash
2 echo
3 set -- $(getopt -q ab:cd: "$@")
4 while [ -n "$1" ]
5 do
6 case "$1" in
7 -a) echo "Found the -a option";;
8 -b) value=$2
9 echo "Found the -b option, Param = $value"
10 shift;;
11 -c) echo "Found the -c option";;
12 -d) value=$2
13 echo "Found the -d option, Param = $value"
14 shift;;
15 --) shift
16 break;;
17 *) echo "$1 is not option";;
18 esac
19 shift
20 done
21
22 count=1
23 for param in $@
24 do
25 echo "Param$count = $param"
26 count=$[ $count + 1 ]
27 done
运行:
3. 使用更高级的getopts
getopt将命令行上选项和参数的处理结后只生成一个输出。
getopts能够和已有的shell参数变量配合默契。
每次调用它时,它一次只处理命令行上检测到的一个参数。处理完所有的参数后,会退出并返回一个大于0的退出状态码。这样就可以循环了。
格式如下:
getopts optstring variable
如果选项有参数就在后面加冒号
要去掉错误消息就在前面加冒号。
getopts会用到两个环境变量:
OPTARG:会保存一个参数值
OPTIND:保存参数列表中getopts正在处理的参数位置。
getopts知道何时停止处理选项,并且把参数留给你处理。
每处理一个选项,OPTIND就会增1,处理完选项时就可以用shift来移动参数。从而处理参数。
例子:
1 #!/bin/bash
2 echo
3 while getopts :ab:c opt
4 do
5 case "$opt" in
6 a) echo "Found -a option";;
7 b) echo "Found -b option, with value:$OPTARG";;
8 c) echo "Found -c option";;
9 *) echo "Unkonw option: $opt"
10 esac
11 done
12
13 echo
14 echo "OPNTING = $OPTIND"
15 shift $[ $OPTIND - 1 ] #这里开始处理参数,先移动参数
16 count=1
17 for param in "$@"
18 do
19 echo "Param$count = $param"
20 count=$[ $count + 1 ]
21 done
运行:
14.5 将选项标准化
有一些选项是标准化了,约定俗成的东西。自己写的脚本中可以支持这些选项。这样用户使用你的脚本就不用查手册了。
比如:
-a 显示所有对象
-c 生成一个计数
-h 显示命令的帮助信息
-I 忽略文本大小写
-v 生成详细输出
……
14.6 获得用户输入
使用场景:脚本运行时可以问个问题,并等待运行脚本的人来回答。
为此提供了read命令
14.6.1 基本的读取
read命令从标准输入或另外一个文件描述符中接收输入。收到输入后read将数据放进一个变量中去。
read 还可以接 –p选项,允许在read命令行指定提示符。
还可以指定多个变量,如果变量数量不够,那么剩下的数据就全部分配到最后一个变量中。
如果没有指定变量名,会放到环境变量REPLY中。
例子:
1 #!/bin/bash
2 echo -n "Please input you name:"
3 read name
4 echo "Hello $name, welcome to xcy program"
5 read -p "Please input you age: " age # 指定提示符
6 echo "you are live:$[ $age * 365 ] days"
7 read -p "step2 Please input you company and num:" company num # 多个变量
8 echo "you company:$company, num:$num"
9 read -p "REPLY test:" # 不值得变量名
10 echo "You input REPLY = $REPLY"
运行:
14.6.2 超时
如果使用了read,脚本会一直等待用户输入。
如果不管脚本是否有数据输入都继续执行下去,就可以指定一个定时器。
-t 指定一个计时器,指定了read命令等待输入的秒数。定时器过期后,read返回一个非0退出状态码。
还可以不对输入过程计时,而是统计字数,字数到了就自动退出,将输入数据赋给变量。
用-n选项,后面接字数
例子:
1 #/bin/bash
2 if read -t 10 -p "Input you name:" name # 计时
3 then
4 echo "Hi $name, welcome"
5 else
6 echo
7 echo "sorry, to slow"
8 fi
9
10 read -n1 -p "Do you want to continue [Y/N]? " answer # 限定字符
11 case $answer in
12 Y) echo
13 echo "you are continue ......";;
14 N) echo
15 echo "Bye Bye!!!";;
16 *) echo
17 echo "Error, Bye";;
18 esac
14.6.3 隐藏方式读取
比如输入密码,不想别人看见,就需要隐藏输入。
加 –s 选项
比如:
1 #!/bin/bash
2 read -s -p "input you Pass:" Pass
3 echo
4 read -s -p "input you Pass again:" Pass1
5 echo
6 if [ $Pass = $Pass1 ] # 字符串比较是否相同
7 then
8 echo "Success!!!"
9 else
10 echo "Falied, Two inconsistent"
11 fi
14.6.4 从文件中读取
每次调用read命令,它都会从文件中读取一行文本。当文本没有内容时,read返回非零退出状态码。
难点在于将文件中的数据传给read命令。最常见的方法是对文件使用cat命令,将结果通过管道直接传给含有read命令的while命令。
例子:
1 #!/bin/bash
2 read -p "Please input you read file name:" name
3 if [ -e $name ] # 是否存在
4 then
5 count=1
6 cat $name | while read line
7 do
8 echo "Line $count:$line"
9 count=$[ $count + 1 ]
10 done
11 else
12 echo "$name not exist"
13 fi
《Linux命令行与shell脚本编程大全》第十四章 处理用户输入的更多相关文章
- 《Linux命令行与shell脚本编程大全》 第四章
4.1 监测程序 1. ps 默认只显示运行在当前控制台下的属于当前用户的进程. 可以接很多选项,比如 -A表示所有进程 -e等. 2. ps -l 查看进程更多信息 UID:启动这些进程的用 ...
- 《Linux命令行与shell脚本编程大全》 第二十七章 学习笔记
第二十七章:shell脚本编程进阶 监测系统统计数据 系统快照报告 1.运行时间 uptime命令会提供以下基本信息: 当前时间 系统运行的天数,小时数,分钟数 当前登录到系统的用户数 1分钟,5分钟 ...
- 《Linux命令行与shell脚本编程大全》 第二十三章 学习笔记
第二十三章:使用数据库 MySQL数据库 MySQL客户端界面 mysql命令行参数 参数 描述 -A 禁用自动重新生成哈希表 -b 禁用 出错后的beep声 -B 不使用历史文件 -C 压缩客户端和 ...
- 《Linux命令行与shell脚本编程大全》 第六章环境变量
很多程序和脚本都通过环境变量来获取系统信息.存储临时数据和配置信息. 6.1 什么是环境变量: bash shell用一个叫环境变量(environment variable)的特性来存储有关shel ...
- 《Linux命令行与shell脚本编程大全》第十三章 更多的结构化命令
本章讨论bash shell的循环命令for.while和until 13.1 for命令 重复执行一系列命令在编程中很常见. bash shell提供了for命令,允许你创建一个遍历一系列值的循环. ...
- 《Linux命令行与shell脚本编程大全》第二十一章 sed进阶
本章介绍一些sed编辑器提供的高级特性. 21.1 多行命令 按照之前的知识,所有的sed编辑器命令都是针对单行数据执行操作的. 在sed编辑器读取数据流时,它会基于换行符的位置将数据分成行,一次处理 ...
- 《Linux命令行与shell脚本编程大全》第十一章 构建基本脚本
11.1使用多个命令 $date;who // 命令列表,加入分号就可以,这样会依次执行.参见5.2.1节 注意区分$(date;who),这个是进程列表,会生成一个子shell来执行 Shel ...
- 《Linux命令行与shell脚本编程大全》 第三章 学习笔记
第三章:基本的bash shell命令 bash程序使用命令行参数来修改所启动shell的类型 参数 描述 -c string 从string中读取命令并处理他们 -r 启动限制性shell,限制用户 ...
- 《Linux命令行与shell脚本编程大全》第十七章 创建函数
可以将shell脚本代码放进函数中封装起来,这样就能在脚本中的任何地方多次使用它了. 17.1 基本的脚本函数 函数:是一个脚本代码块,可以为其命名并在代码中任何位置重用. 17.1.1 创建函数 有 ...
- 《Linux命令行与shell脚本编程大全》 第五章理解shell
5.1 1. cat /etc/passwd 可以查看每个用户自己的默认的shell程序. 2.默认的交互shell会在用户登录某个虚拟控制台终端时启动. 不过还有另外一个默认的shell是/bin/ ...
随机推荐
- Hexo+Github搭建博客
要使用Hexo,需要在你的系统中支持Nodejs以及Git,如果还没有,那就开始安装吧! 安装Node.js 下载Node.js 参考地址:安装Node.js 安装Git 下载地址:http://gi ...
- Java常见异常处理
Exception类: 在java中用类的形式对不正常情况进行了描述和封装对象,异常就是java通过面向对象的思想将问题封装成了对象. 异常发生的原因有很多,通常包含以下几大类: 用户输入了非法数据. ...
- 如何删除错误提交的 git 大文件
早上小伙伴告诉我,他无法拉下代码,我没有在意.在我开始写代码的时候,发现我的 C 盘炸了.因为我的磁盘是苏菲只有 256G 放了代码就没空间了,于是我查找到了原来是我的代码占用了居然有 2000+M ...
- 基于FFMpeg的C#录屏全攻略
最近负责一个录屏的小项目,需要录制Windows窗口内容并压缩保存到指定文件夹,本想使用已有的录屏软件,但是本着学习的态度去探索了FFMpeg,本文主要介绍基于FFMpeg开源项目的C#录屏软件开发. ...
- Java的绝对路径和相对路径
Java的绝对路径和相对路径 参考:http://blog.csdn.net/u011225629/article/details/46872775 1. 绝对路径 以根部件开始的路径是绝对路径,比如 ...
- Java基础笔记5
方法(函数) 就是一块可以重复调用的代码块. 比如.100行代码. 在多处使用. 方法的格式 public static 返回类型 方法名称(参数列表){ } 返回类型:当方法被调用时,把返回内容 交 ...
- IE页面刷新ocx插件被释放,野指针非阻塞Sleep问题。
做一个视频页面,自动化测试的时候崩溃.排查了半天,才发现虚表为NLL,然后调用的已经释放对象里面的函数. 问题出在哪呢?出在了左边的非阻塞Sleep的地方.对象已经释放掉了,但是好在阻塞循环,调用st ...
- enum(枚举类型)
可以使用枚举类型声明代表整数常量的符号名称. 通过enum,创建一个新类型,并指定它可以拥有的值.(就像平常用一个整形变量,我们指定它等于0的时候代表什么,1呢,2呢...而通过枚举,就增加了程序的可 ...
- setup 命令中防火墙配置选项无法打开
故障提示 1.1 如何让setup 命令中防火墙配置生效 1.1.1 CentOS系统找不到setup命令工具的解决方法 yum -y install setuptool #安装setup命令工具 y ...
- 桌面消息通知:HTML5 Notification
先上一段完整代码 //注册权限 Notification.requestPermission(function (status) { // 这将使我们能在 Chrome/Safari 中使用 Noti ...