《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/ ...
随机推荐
- Delphi实现电脑端微信图片文件解密
电脑端微信收到图片后是存在了“C:\Users\系统用户名\Documents\WeChat Files\微信帐号\Data”目录下的,但文件不能直接使用图片浏览器打开的,因为做了一些加密,之前有个朋 ...
- 完整Log4Net配置信息
<?xml version="1.0" encoding="utf-8" ?> <configuration> <configSe ...
- vue 父组件传递子组件事件
在开发中,碰到一个需要从父组件传入方法,子组件点击触发,说白了就是,把方法传入给子组件调用 <el-col v-for='data in spreadFormat.icons' class=&q ...
- Django(一)
Django 一.什么是web框架 框架,即framework,特指为解决一个开放性问题而设计的具有一定约束性的支撑结构,使用框架可以帮你快速开发特定的系统,简单地说,就是你用别人搭建好的舞台来做表演 ...
- RabbitMQ 笔记-Exchanges
Procuder Publish的Message进入了Exchange.接着通过"routing keys", RabbitMQ会找到应该把这个Message放到哪个queue里. ...
- [mysql使用(2)] mysql的一些语法与Oracle的差别
一.表空间 mysql的表空间有共享表空间和独占表空间,独占表空间,其实就是一张表一个表空间,其实也就是一张表一个数据文件,共享表空间似乎有点类似oracle的表空间,不同的表可以保存在同一个数据文件 ...
- python分布式环境下的限流器
项目中用到了限流,受限于一些实现方式上的东西,手撕了一个简单的服务端限流器. 服务端限流和客户端限流的区别,简单来说就是: 1)服务端限流 对接口请求进行限流,限制的是单位时间内请求的数量,目的是通过 ...
- Azure 基础:使用 powershell 创建虚拟机
在进行与 azure 相关的自动化过程中,创建虚拟主机是避不开的操作.由于系统本身的复杂性,很难用一两条简单的命令完成虚拟主机的创建.所以专门写一篇文章来记录使用 PowerShell 在 azure ...
- SpringMVC 集成redis
一.下载导入jar 二.配置redis 1.创建redis.properties # Redis settings #redis.host=192.168.20.101 #redis.port= #r ...
- Ajax中与服务器的通信【发送请求与处理响应】
一.发送请求 Ajax中通过XMLHttpRequest对象发送异步方式的后台请求时.通常有两种方式的请求,一种是GET请求,另一种是POST请求.发送请求一般要经过4个步骤分别是: (1)初始化XM ...