处理用户输入
1.命令行参数
向shell传递数据的最基本方法是使用命令行参数
bash shell会将一些称为位置参数(positional parameter)的特殊变量分配给输入到命令行的所有参数,位置参数变量的标准的数字是:$0是程序名,即脚本名,$1是第一个参数,$2是第二个参数,依次类推,当第九个变量之后,必须使用花括号标示,比如${10},这项技术允许向脚本添加任意多个参数。例如:
./test.sh 1 2 3 4 5 6 7 8 9 10 11
使用$0获取脚本名,存在一个潜在问题,即$0获取的为命令和脚本名,basename
可以解决这个问题
name=$(basename $0)
获取脚本名,同时,通过dirname
可以获取路径名
2.测试参数
在使用命令行参数前,应对参数进行测试,避免异常,可使用条件测试
内容判断:if [ -n "$1" ]
进行判断
3.参数统计
特殊变量$#
统计参数个数,数量判断:if [ $# -ne 2 ]
获取最后一个参数,不可以使用${$#}
,因为不可以在{}中使用$,具体原因不详,获取最后参数的两种方法:
1.将
$#
赋值给变量,再使用$获取,例如para=$#;echo $para
2.使用${!#}
获取,echo ${!#}
当没有参数的时候,可获取脚本名,需注意使用basename
获取所有参数,通过$@或$*
,区别在于:
$*
变量会将所有参数当作一个单词保存
$@
变量会将所有参数当作多个独立的单词
使用for遍历所有参数即可理解,另外所有参数不包括$0,请注意
4.移动变量
bash shell使用shift
来操作命令行参数,根据他们的相对位置来移动参数
基本原理:
在使用shift的时候,会将每个参数向左移动一个位置,即$3移动到$2位置,$2移动到$1位置,$1被删除
当移完所有参数,$1则为空,由此可以判断遍历完成
但所需要注意$0为程序名,不会移动,不受影响
shift使用格式:shift [n]
,不添加n表示默认移动一个位置,如果加n则移动n个位置,可以跳过不使用的参数
注意:被删除的参数,无法再恢复使用,当在脚本的前部移出了参数,再后面的代码部分将不可使用该参数
5.处理选项
可以像bash一样定义选项,选项是根在单破折号(-)后面的单个字符,例如ls -l,l即为选项
选项和参数:通过选项脚本可以执行特定功能,而参数是向脚本传递的数据
在脚本中添加选项,通过使用case和shift进行提取和处理,例如
while [ -n "$1" ];do
case "$1" in
-a) echo "found the -a option";;
-b) echo "found the -b option";;
-c) echo "found the -c option";;
*) echo "found no option";;
esac
shift
done
]# . test.sh -a -b -d
found the -a option
found the -b option
found no option
分隔参数和选项,当需要同时对脚本传递参数和选项的时候,使用双破折号(--
)进行分隔
while [ -n "$1" ];do
case "$1" in
-a) echo "found the -a option";;
-b) echo "found the -b option";;
-c) echo "found the -c option";;
--) shift
break;;
*) echo "found no option";;
esac
shift
done
]# . test.sh -a -b -d -- test1 test2
其中–)shift用于移出参数中的–
处理带值的选项,当某些选项需要使用额外的参数值时,需要特殊处理
例如:
]# . test.sh -a -b PARAMETER -d -- test1 test2
需要在脚本中的case语句中加入:
-b) param="$2"
echo "found the -b option, with param is $param"
shift;;
注意:如果选项后跟着多个参数,需要shift n,但此时仍不能成立合并选项的情况,例如-ad
getopt命令
是处理选项和参数工具,它能够识别命令行参数,格式
getopt optstring parameters
optstring
定义了命令行有效的选项字符,并定义了哪些选项需要参数,在每个需要参数值的选项后面加冒号,进而由getopt解析,例如
getopt ab:cd -a -b test1 -cd test2 test3
其中b的参数为test1,而test2、3为常规参数,-acd为不带特殊参数的选项,getopt会自动将cd分成两个单独选项
如果脚本调用了不在optstring中的选项,默认程序会报错,可使用-q来屏蔽此类消息,必须在optstring之前使用getopt的选项
getopt -q ab:cd -a -b test1 -cd test2 test3
在脚本中使用getopt,比较麻烦,方法:
使用getopt命令生成格式化后的版本替换已有的命令行选项和参数,期间需要使用
set
命令
简要处理流程:
set
命令的选项之一双破折号(–),会将命令行参数替换成set命令的命令行值
该方法将原始脚本的命令行参数传给getopt命令
之后再将getopt命令的输出传给set命令,用getopt格式化的命令行参数来替换原始的命令行参数
格式
set -- $(getopt -q ab:cd "$@")
在调用脚本的时候就不需要添加–
./test.sh -a -b test1 -cd test2 test3
但getopt不擅长处理带空格和引号的参数值,会将空格当作分隔符,此时需要更强大的getopts
getopts命令
是bash shell的builtin,和getopt很像,但多了一些扩展功能,脚本使用也不需要调用set,格式
getopts optstring variable
getopts会将选项列在optstring中,参数保留在variable中。optstring类似getopt中的该选项,但是如果要去掉错误信息,可以在optstring前加冒号,例如如
:ab:cd
getopts会使用两个参数,如果选项需要跟一个参数值,OPTARG环境变量就会保存这个值,OPTIND环境变量保存了参数列表中getopts正在处理的参数位置,这样就能在处理完选项后继续处理其他参数了。
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";;
*) echo "found no option $opt";;
esac
done
]# ./test.sh -ab "test1 tssd" -c
需要注意当某选项包含多个参数时,需要加双引号,case中选项不需要加单破折号-。
]# ./test.sh -abtest1 -c
选项和参数之间可以不加空格,但参数和后面选项之间需要加
getopts会将命令行上未定义的选项统一输出成问号?
getopts只能处理选项,当处理完选项后,剩余的参数,可以使用shift和OPTIND值来移动参数
shift $[ $OPTIND -1 ],此时把指针移动到最后一位选项之后,其他的可以通过$@获取参数
#!/bin/bash
echo
while getopts :ab:cd opt;do
case "$opt" in
a)echo "found -a option";;
b)echo "found -b option, with parameter value $OPTARG";;
c)echo "found -c option";;
d)echo "found -d option";;
*)echo "Unknow option: $opt";;
esac
done
echo "parameter current postion is $OPTIND"
shift $[ $OPTIND -1 ]
echo
count=1
for param in "$@";do
echo "parameter #$count: $param"
count=$[ $count+1 ]
done
至此我们在shell脚本中使用全功能命令行选项和参数处理工具
6.linux常用命令行选项含义
a 显示所有对象
c 生成一个计数
d 指定一个目录
e 扩展一个对象
f 指定读取数据的文件
h 帮助信息
i 忽略大小写
l 产生输出的长格式版本
n 使用非交互模式
o 将输出重定向到指定文件
q 以安静模式运行
r 递归处理目录或文件
s 以安静模式运行
v 生成详细输出
x 排除某个对象
y 对所有问题回答yes
7.获取用户输入
read命令从标准输入或另一个文件描述符中接受输入,收到输入后,read命令会将数据存入一个变量。
read options [context] variable1,variable...
可指定多个变量,也可以不指定变量,此时将接收的所有数据放进环境变量的REPLY
中
-p:允许在read命令行指定提示信息,例如:read -p "enter your age:" age
-t:设置超时时间,当计时器过期后,read命令会返回一个非零退出状态码
-n:指定输入字符个数,-n1,一个字符
-s:隐藏显示输入信息
从文件中读取数据,每次调用read命令,都会从文件中读取一行文本,当文件中再没有内容时,read命令会退出并返回非零退出状态码,而read本身无法读取文件,可以借助cat和管道
cat user.csv|while read line;do