【读书笔记】Linux命令行与Shell脚本编程大全--处理用户输入

1. 命令行参数

1.1 读取参数

bash shell会将一些称为位置参数(positional parameter)的特殊变量分配给输入到命令行中的所有参数(包括shell所执行的脚本名称)。
位置参数变量标准的数字$0是程序名,$1是第一个参数,通常依次到$9
eg:

a=1
for((num=1;num<$1;num++))
do
        a=$[ $a+$num ]
done
echo $a
#11

notice:

  1. 需要输入更多的命令行参数,则每个参数都必须用空格分开
  2. shell脚本会自动将命令行参数的值分配给变量,不需要作任何处理。
  3. 当遇到传入参数带有空格时,记得用引号包括起来(单双引号都可)。
  4. 当命令行参数超过9个时候,第10个参数以及第10+n个参数的引用需要使用花括号。如${10}

1.2 读取脚本名–$0

以用$0参数获取shell在命令行启动的脚本名。

读取脚本名有如下需要注意的:

  1. 如果使用另一个命令来运行shell脚本,命令会和脚本名混在一起,出现在$0参数中。
  2. 当传给$0变量的实际字符串不仅仅是脚本名,而是完整的脚本路径时,变量$0就会使用整个路径。

Q:如何避免上述问题?
A:使用basename命令即可。

eg:

echo $0
path=$(basename $0)
echo $path

#/home/hogoadr/workspace/share/george/shell/myshell
#myshell

1.3 测试参数–-n

当脚本认为参数变量中会有数据而实际上并没有时,脚本很有可能会产生错误消息。
在使用参数前一定要检查其中是否存在数据

可以使用**-n**测试来检查命令行参数$1中是否有数据。

eg:

扫描二维码关注公众号,回复: 11077388 查看本文章
if [ -n "$1" ]					#使用 -n 测试 是否执行使用参数1的相关代码块
then
a=1
for((num=1;num<$1;num++))
do
        a=$[ $a+$num ]
done
echo $a
else
        echo "no parameter 1 "
fi

#no parameter 1

2.特殊参数变量

2.1 参数统计–$#

特殊变量$#含有脚本运行时携带的命令行参数的个数。可以在脚本中任何地方使用这个特殊变量,就跟普通变量一样。这样就可以避免多个参数需要一个一个测试的繁琐。

eg:

if [ $# -eq 2 ];then
        echo "parameter is 2"
elif [ $# -eq 1 ];then
        if [ -n "$1" ];then
                a=1
                for((num=1;num<$1;num++))
                do
                        a=$[ $a+$num ]
                done
                echo $a
        fi
else
        echo "no parameter 1 "
fi

#根据携带参数走不同分支

notice:

  1. if-then语句用**-ne**测试命令行参数数量。如果参数数量不对,会显示一条错误消息告知脚本的正确用法
  2. ${!#}用来获取命令行中最后一个参数
  3. 命令行上没有任何参数时$#的值为0,params变量的值也一样,但${!#}变量会返回命令行用到的脚本名

2.2 抓取所有数据–$*$@[遍历命令行的绝妙方法]

命令 描述
$* 用来轻松访问所有的参数 1.将命令行上提供的所有参数
当作一个单词保存
2.基本上$*变量会将这些参数视为一个整体
而不是多个个体
能够在单个变量中存储所有的命令行参数
$@ 用来轻松访问所有的参数 将命令行上提供的所有参数当作同一字符串中的多个独立的单词,通常使用for命令遍历得到每个参数值

eg:

cnt=1
for para in $"$*"
do
	echo "\$* $cnt = $para"
	cnt=$[ $cnt + 1 ]
done

cnt=1
for para in $"$@"
do
	echo "\$@ $cnt = $para"
	cnt=$[ $cnt + 1 ]
done

#$* 1 = 5:8:6:9:7
#$@ 1 = 5
#$@ 2 = 8
#$@ 3 = 6
#$@ 4 = 9
#$@ 5 = 7

3.移动变量–shift命令[遍历命令行参数的另一个好方法]

shift命令会根据它们的相对位置来移动命令行参数。(遍历命令行参数的另一个好方法,在不知道有多少个命令行参数的时候,只读第一个参数)

notice:

  1. 在使用shift命令时,默认情况下它会将每个参数变量向左移动一个位置
  2. 使用shift命令的时候要小心。如果某个参数被移出,它的值就被丢弃了,无法再恢复
  3. 可以一次性移动多个位置,即给shift 命令后面跟个n个位置参数,指明要移动的位置数。
  4. 通过使用shift命令的参数,可以轻松的跳过不需要的参数。

eg:

echo 
count=1 
while [ -n "$1" ] 
do 
 echo "Parameter #$count = $1" 			#不知道实际参数个数,只取第一个参数
 count=$[ $count + 1 ] 
 shift 
done

#Parameter #1 = 5
#Parameter #2 = 8
#Parameter #3 = 6
#Parameter #4 = 9
#Parameter #5 = 7

4.处理选项

4.1 查找选项

bash shell 脚本可以像处理命令行参数一样处理命令行选项

处理命令行选项需要注意如下两点:

  1. 分离参数和选项;
  2. 处理带值的选项。

Q:如何分离参数和选项?
A:Linux使用标准方法是使用特殊字符。双破折线(–),shell会用双破折现线来表明选项列表的结束。

ps:处理带值的选项通常包括注意选项的合并。eg:ls -la

4.2 使用getopt命令-格式化命令行选项和参数

getopt命令可以接受一系列任意形式的命令行选项和参数,并自动将它们转换成适当的格式,是一个在处理命令行选项和参数时非常方便的工具。

其格式如下:

getopt optstring parameters

optstring是这个过程的关键所在。
它定义了命令行有效的选项字母,还定义了哪些选项字母需要参数值

其流程如下:
首先,在optstring中列出你要在脚本中用到的每个命令行选项字母。
然后,在每个需要参数值的选项字母后加一个冒号。
getopt命令会基于你定义的optstring解析提供的参数。

eg:

$ getopt ab:cd -a -b test1 -cd test2 test3
 -a -b test1 -c -d -- test2 test3

ps: getopt -q 选项可以忽略错误信息(若指定了一个不在optstring中的选项)

Q:如何在脚本中使用getopt命令?
A:方法是用getopt命令生成的格式化后的版本来替换已有的命令行选项和参数。用set命令能够做到。
set命令的选项之一是双破折线(–),它会将命令行参数替换成set命令的命令行值
该方法会将原始脚本的命令行参数传给getopt命令,之后再将getopt命令的输出传给set命令,用getopt格式化后的命令行参数来替换原始的命令行参数。
其格式如下:

set -- $(getopt -q ad:cd "$@")

现在原始的命令行参数的值会被getopt命令的输出替换,而getopt命令以及将原始命令行参数进行了格式化。

notice:
getopt命令并不擅长处理带空格和引号的参数值。它会将空格当作参数分隔符,而不是根据双引号将二者当作一个参数

4.3 使用更高级的getopts–避开getopt命令的劣势扩展了一些功能

getopts命令(注意是复数)是bash shell的内建。相比getopt命令多了一些扩展功能并且避开了getopt命令不擅长处理带空格和引号的参数值。

命令 区别
getopt 1.将命令行上选项和参数处理后只生成一个输出
getopts 1.能够和已有的shell参数变量配合默契
2.一次只处理命令行上检测到的一个参数
3.处理完所有参数后,退出并返回一个大于0的退出状态码
4.可以在参数值中包含空格
5.可以将选项字母和参数值放在一起使用而不用加空格
6.能够将命令行上未定义的选项统一输出成问号

getopts命令格式如下:

getopts optstring variable

notice:

  1. optstring同样和getopt一样也是关键;
  2. 有效的选项字母都会列在optstring中,如果选项字母要求有参数值,就加一个冒号;
  3. 要去掉错误消息,可以在optstring之前加一个冒号,这和getopt命令显得不同
  4. getopts命令将当前参数保存在variable中;
  5. getops命令解析命令行选项时会移除开头的单破折线。

ps:
1.getopts命令会用到两个环境变量。(OPTARG和OPTIND)
OPTARG环境变量会保存选项需要跟的参数值;
OPTIND环境变量保存了参数列表中getopts命令正在处理的参数位置。(getopts命令在处理每个选项时,OPTIND的值会增一)

5.将选项标准化

在这里插入图片描述

6.获得用户输入–read

6.1 基本的获取

read命令从标准输入(键盘)或另一个文件描述符中接收输入。

ps:

  1. echo -n 选项 不会在字符串末尾输出换行符。
  2. read命令使用-p选项,允许直接在read命令行指定提示符。(若使用了-p选项而没有指定提示符,则会出乎所料哦)。
  3. read命令会将提示符输入的所有数据分配给单个变量(若变量数量不够,剩下的数据就全部分配给最后一个变量,因此要么指定多个变量,要么全部分配给最后一个变量)。
  4. read命令行中没有指定变量,则read命令会将它收到的任何数据都放进特殊环境变量REPLY中。

eg:

read -p name
echo $name
read name
echo $name
read -p "Please input you namef: " namef
echo $namef 
read -p "Please input you namef: " names
echo $names
read
echo $REPLY

#namewang heng
#
#wang heng
#wang heng
#Please input you namef: wang
#wang
#Please input you namef: heng
#heng
#who
#who

6.2 超时–read需要超时判断

Q:如何做到read超时判断?
A:有如下两种办法:

  1. read -t 计时判断。-t选项指定一个计时器,指定了read命令等待输入的秒数,当计时器过期后,read命令会返回一个非零的退出状态码。
  2. 也可以让read命令来统计输入的字符数(-n)。当输入的字符达到预设的字符数时,则自动退出,将输入赋值给变量。

eg:

#read -t
if read -t 5 -p "Please input a num: " num;then
        echo "the num is $num"
else
        echo "is too slow"
fi

#read -n
read -n1 -p "Continue?[Y/N]" answer		#将-n选项和值1一起使用,告诉read命令在接受单个字符后退出
case $answer in
Y | y)  echo "continue..";;
N | n)  echo
        echo "not continue.."
        exit;;
esac
echo "shell is over.."

#Please input a num: 2
#the num is 2
#Continue?[Y/N]n
#not continue..

#Please input a num: is too slow
#Continue?[Y/N]ycontinue..
#shell is over..

6.3 隐藏方式读取–-s典型应用于密码输入上

-s选项可以避免在read命令中输入的数据出现在显示器上(实际上,数据会被显示,只是read命令会将文本颜色设成跟背景色一样)

eg:

#read -s
if read -t 5 -s -p "Please input the passwd: " pswd;then
        echo "the pswd is $pswd"
else
        echo "is too slow"
fi

#Please input the passwd: the pswd is 123

6.4 从文件读取

每次调用read命令,它都会从文件中读取一行文本
当文件中再没有内容时,read命令会退出并返回非零退出状态码

Q:如何将文件内容传输给read命令?
A:最常见的方法是对文件使用cat命令,将结果通过管道直接传给含有read命令的while命令。

eg:

cnt=1
cat 3_1_while.log | while read line
do
	echo "read line$cnt is $line"
	cnt=$[ $cnt + 1 ]
done

#read line1 is 5
#read line2 is 4
#read line3 is 3
#read line4 is 2
#read line5 is 1

申明:文中没特殊注明,图皆来自Linux命令行与shell脚本编程大全<第三版>。

发布了91 篇原创文章 · 获赞 17 · 访问量 5万+

猜你喜欢

转载自blog.csdn.net/qq_23327993/article/details/104637410
今日推荐