[bash]命令行参数、getopt系列命令格式化命令行字符串

1. 读取和测试命令行参数:

#!/bin/bash

if [ -n "$1" ]	#必须先测试参数是否读入(即命令行上是否真正传了参数),使用""括起来,参数允许是含有空格的字符串
#如果使用了未读入的参数会报错!
then
	echo Have read it!
else
	echo "Can't identify it!"
fi

fac=1
for (( n = 1; n <= $1; n++ ))#计算阶乘
do
	fac=$[ $fac * $n ]
done
echo $fac
其中环境变量$0表示命令名本身,$1 ~ $9表示接下来的1到9个命令行参数

2. 读取多个命令行参数:

#!/bin/bash

echo The first parameter is $1
echo The second parameter is $2
echo The conduct is $[ $1 * $2 ]    #计算两个参数的乘积

3. 参数是字符串并且带有空格:

#!/bin/bash

#如果参数字符串含有空格,则在输入命令的时候将含有空格的字符串用''或""括起来即可
echo Hello, $1!

4. 读取任意多的参数:

#!/bin/bash

#超过第9号参数之后的参数引用的时候使用${}形式就行了
#通过这种方法可以读取任意多个参数

echo The tenth parameter is ${10}
echo The eleventh parameter is ${11}

5. 读取脚本名称并获得脚本的基名:

#!/bin/bash

echo The command entered is: $0	#命令行输入的名称如何输出就是如何
echo The command entered is: `basename $0`	#获取文件的基名,可以去掉前面的路径只包含文件名本身

6. 利用环境变量$#获取参数的个数(但是不包括$0):

#!/bin/bash

for (( i = 1; i <= $#; i++ ))
do
	echo $i
done
一个简单的应用:

#!/bin/bash

if [ $# -ne 2 ]	#如果错误的输入参数则提醒如何正确使用
then
	echo Usage: test a b
else
	echo $[ $1 + $2 ]	#正确输入则输出求和
fi

7. ${!var}——利用变量来选择具体使用哪一个命令行参数:

#!/bin/bash

echo ${!#}	#获取最后一个参数
a=3
echo ${!a}	#获取第三个参数

for (( i = 1; i <= $#; i++ ))	#打印所有参数
do
	echo ${!i}
done

8. 迭代命令行参数:

#!/bin/bash

echo \$*: $*
echo \$@: $@

#这两种方法(即$@和$*不用""括起来)
#则迭代时无视用命令输入时的"",即使是""里面的空格也会被当成参数的分隔符
for x in $*
do
	echo $x
done

echo "*********"
for x in $@
do
	echo $x
done

#会将整个命令行的所有参数当成一个迭代值
echo "*********"
for x in "$*"
do
	echo $x
done

#将命令行参数逐个迭代,并将""括起来的参数视作一个迭代值(包括""中的空格)
#推荐使用!!!
echo "*********"
for x in "$@"
do
	echo $x
done

#同上
echo "*********"
for (( i = 1; i <= $#; i++ ))
do
	echo ${!i}
done

9. 使用shift命令来移动参数:

#!/bin/bash

while [ -n "$1" ]
do
	echo $1
	shift	#不带参数默认将所有参数左移一位,这样$4变成#3,$3变成$2,而$1将被永久丢弃(即被删除,不可恢复),但$0始终不会变,永远都是命令名
done

while [ -n "$1" ]
do
	echo $1
	shift 2	#一次左移两个参数
done

10. 标准的命令行格式和getopt命令:

标准的命令行格式为:命令名 [-选项1 选项1的参数列表] [-选项2 选项2的参数列表].. -- 参数1 参数2

同时也支持多个选项的合并,比如-abc

getopt命令可以让输入的乱七八糟的命令格式化成标准形式:

#!/bin/bash

#首先getopt的第一个参数是一个字符串optstring
#其中定义了所有的命令选项,共有abcde这5种选项
#其中:表示选项b后面带一个选项参数,只能是一个,如果输入命令的时候有多个会出问题
#下一个参数就是命令输入时的选项和参数的字符串
echo `getopt ab:cde -ab sdf -cdef dsf "sdfk sdf" 1 23424`
#输出为-a -b sdf -c -d -e -- dsf sdfk sdf 1 23424
#--用以分隔选项部分和参数部分

11. 使用getopt、case以及shift来进行命令解析:

#!/bin/bash

set -- `getopt -q ab:cde "$@"`	#利用set命令将原始命令行参数的值替换成格式化后的值
#在Linux中如果输入了不存在的选项,则在使用getopt进行格式化时会报错
#提示你使用了不存在的非法选项,但是无论如何getopt命令最终转化后的标准形式
#都是忽略不存在的选项的,因此可以给getopt命令添加一个选项-q使其不输出错误信息
#即set -- `getopt -q ab:cde "$@"`

while [ -n "$1" ]
do
	case "$1" in
		-a) echo Found the -a option;;
		-b) echo Found the -b option, with parameter $2
			shift;;	#需要额外shift掉选项参数
		-c)	echo Found the -c option;;
		-d) echo Found the -d option;;
		-e) echo Found the -e option;;
		--) shift	#getopt会化成标准命令行参数形式,以--作为选项和参数的间隔
			break;;	#表示选项部分已经读取完毕,跳出循环接着读取参数部分
		*)	echo $1 is not an option;; #getopt会自动忽略不存在的选项,因此这条语句多余,放在这里只是做一个提醒!
	esac
	shift
done

cnt=1
while [ -n "$1" ]
do
	echo Parameter $cnt: $1
	cnt=$[ $cnt + 1 ]
	shift
done

$ bash test.sh -afcb 3224 -de sdkjf 234 ssD

#output:
getopt: illegal option -- f
Found the -a option
Found the -c option
Found the -b option, with parameter 3224
Found the -d option
Found the -e option
Parameter 1: sdkjf
Parameter 2: 234
但遗憾的是getopt不擅长处理带空格的参数,比如"sdf sdf"getopt会将其当成sdf和sdf两个参数处理而忽略""的作用


12. 使用while和更高级的getopts命令来j解析命令行参数:

getopts更高级的地方:

1)解析完选项部分之后原始命令行参数字符串的值不会改变;

2)可以识别参数中的空格(参数字符串中含有空格);

3)支持选项和选项参数连起来写;

4)对于不存在的(非法的)选项会解析成一个?符号供程序员判断,而不是自动忽略;

#!/bin/bash

#当选项部分全部解析完之后getopts命令会返回非0码农而自动退出循环
#将剩下的参数部分留给你处理
#并且循环过程中不需要shift,这就意味着循环退出后并不会影响原始的命令行参数值
#两个环境变量,$OPTIND表示当前处理到了几号参数,如果选项和选项参数写在一起则会当成一个,分开则会当成两个参数
#getopts命令会将每次解析出来的选项存入自定义的变量opt中,而选项参数则存入环境变量$OPTARG中

#getopts的第一个参数仍然是optstring,意义和getopt命令的optstring参数一样,只不过如果在开头加一个:的效果和getopt的-q选项一样,都表示忽略非法的选项
while getopts :ab:c opt
do
	echo $OPTIND
	case $opt in
		a) echo Found the -a option;;	#第一个和getopt不一样的地方,解析后会去掉-符号
		b) echo Found the -b option, with value $OPTARG;;
		c) echo Found the -c option;;
		*) echo Unknown option: $opt;;	#对于非法的选项会返回一个符号?并且$OPTIND不做计数
	esac
done

shift $[ $OPTIND - 1 ]	#选项解析后$OPTIND停留在选项之后的第一个参数上,所以要左移OPTIND - 1位从而将选项部分去掉

echo "********"
for var in "$@"
do
	echo $var
done
$ bash test.sh -axbsdf134 -c sdkf 234 sfd iii "45sd   xxxx"

#这里体现出了getops的三大新亮点
#output:
1
Found the -a option
1
Unknown option: ?	#一:对于不存在的(即非法的)选项将返回字符?
2
Found the -b option, with value sdf134	#二:对于选项字母和选项参数写在一起的也能解析
3
Found the -c option	#选项部分解析完之后getopts命令能返回大于0的状态码而自动退出while循环
********
sdkf
234
sfd
iii
45sd xxxx	#三:参数中多个连续的空格会当成一个空格,这里getopts对空格敏感

你可能感兴趣的:(shell,命令行参数的读取和处理)