天天看点

shell脚本学习五(处理用户输入)

处理用户输入:

 1、命令行参数

       向shell脚本传递数据的最基本的方法是使用命令行参数,命令行参数允许在运行脚本时向命令行添加数据。

2、读取参数

       bash shell中有一些特殊变量叫做 位置参数,位置变量参数是标准的数字:$0 是程序名,$1 是第一个参数,$2是第二个参数,以此类推,直到第九个参数$9 ,$0~$9 可以定义在脚本中,通过命令行向其赋值。

shell脚本学习五(处理用户输入)

shell脚本学习五(处理用户输入)

          当向shell脚本传递字符串时,如果希望将多个字符串当做一个变量,需要加上单引号 ' '

shell脚本学习五(处理用户输入)
.

shell脚本学习五(处理用户输入)

          如果脚本需要的命令行参数不止9个,你仍然可以处理,但是需要稍微修改一下变量名,在第9个变量之后,你必须在变量数字周围加上花括号,比如  ${ 10 }

shell脚本学习五(处理用户输入)

shell脚本学习五(处理用户输入)

3、读取脚本名

         可以使用$0 参数获取shell在命令行启动的脚本名,这在编写多功能工具时很方便

           (同样的脚本如果需要根据不同的脚本名执行不同的功能时,就需要用到 $0 了)

shell脚本学习五(处理用户输入)

shell脚本学习五(处理用户输入)

            但是出现一个潜在的问题,如果使用另一个命令来执行脚本,命令会和脚本名混合在一起出现出现在$0参数中

shell脚本学习五(处理用户输入)

               这不是唯一的问题,当传给$0 变量的实际字符串不仅仅是脚本名,而是完整的脚本路径时,变量$0就会使用整个路径

shell脚本学习五(处理用户输入)

        解决这一问题可以使用basename命令,它会返回不包含路径的脚本名

shell脚本学习五(处理用户输入)

shell脚本学习五(处理用户输入)

        现在可以结和$0 和basename 来编写基于脚本名执行不同功能的脚本了。

shell脚本学习五(处理用户输入)

shell脚本学习五(处理用户输入)

4、 特殊参数变量:

           $# 含有脚本运行时携带的命令行参数的个数,可以在脚本中任何地方使用这个特殊变量,就跟普通变量一样

shell脚本学习五(处理用户输入)

shell脚本学习五(处理用户输入)

     基于$#实现特定功能:

shell脚本学习五(处理用户输入)

shell脚本学习五(处理用户输入)

      5、 抓取命令行上提供的所有参数: $*     [email protected]

              区别就是: $*       会将所有参数当成单个参数

                                 [email protected]     会单独处理每个参数

shell脚本学习五(处理用户输入)

shell脚本学习五(处理用户输入)

 6、移动变量:

         下面这个脚本通过shift命令实现了使用一个参数完成多个数据的遍历,当第一个参数的长度为0时,循环结束。测试完第一个参数后,shift命令会将所有的参数的位置移动一个位置。

 ( 要注意的是:使用shift命令时,一定要小心,如果某个参数被移出,它的值就被丢弃了,无法再恢复 )

shell脚本学习五(处理用户输入)

                   留个小疑问:为什么 -n  判断$1 是否为0时要加上双引号?

shell脚本学习五(处理用户输入)

          shift 也可以一次性移动多个位置,例如: shift  2  一次移动2 

               注意:我们来看下面这个例子,我特意检测了一下当只有 一个特殊变量$1却有多个参数时shift在while和case中的具体如何工作的

shell脚本学习五(处理用户输入)

            此时我们在脚本中先不使用shift,看看有多个选项时情况如何:

          ( 我们发现它会进行一个死循环,一直输出-a 选项,不能够读取之后的选项 )

shell脚本学习五(处理用户输入)

             此时我们加上shift,重新运行你会发现一切正常

shell脚本学习五(处理用户输入)
shell脚本学习五(处理用户输入)

             这说明 在while 和 case 中 ,每执行完一个选项,就需要shift一次,将原来的选项移出以此来读取新的选项,这对我们理解接下来的 带参数的选项很有帮助   

7、 处理选项:

shell脚本学习五(处理用户输入)

            用一组普通的选项和参数来运行这个脚本,结果说明在处理时脚本认为所有的命令行参数都是选项

shell脚本学习五(处理用户输入)

          当脚本遇到双破折线时,它会停止处理选项,并将剩下的参数都当做命令行参数。

shell脚本学习五(处理用户输入)

8、处理带值的选项

          有的选项会带上一个额外的参数值,当命令行选项要求额外的参数时,脚本必须能检测到并正确处理。

         ( 这种情况下,如$ ./testing.sh  -a test1  -b  -c -d   test2 ) 

shell脚本学习五(处理用户输入)

(  此处执行此脚本带有命令行参数为:  ./difOption.sh  -a  -b  test  -c   

                如上文所说,先将 -a 存入$1变量,执行完-a 选项之后执行do的shift命令将-a 选项移出,遇到-b 选项将其存入$1,因为-b选项带有参数test,所以需要另外准备一个变量$2来存入参数值test,执行完-b选项之后,在-b选项之后执行一次shift将$1中的-b值移出,再在while循环最后执行一次shift将被移入$1的参数test也移出(所以此处是执行了两次shift ),最后在将-c选项读入$1变量,自后执行完毕退出)

shell脚本学习五(处理用户输入)

 9、使用getopt命令

                9.1 命令的格式

            getopt命令可以接受一系列任意形式的命令行选项和参数,并自动将它们转换成适当的格式,其命令格式如下:

                getopt   optstring   parameters

             optstring 定义了命令行有效的选项字母,还定义了哪些选项字母需要参数值,在optstring中列出你要在脚本中用到的每个命令行选项字母,然后,在每个需要参数值的选项字母之后加一个冒号。getopt命令会基于你定义的optstring解析提供的参数

例如:  $ getopt  ab:cd  -a  -b  test1 -cd  test2   test3

                           (      -a  -b  test1   -c  -d   --  test2 test3    ) 

      optstring定义了四个有效选项字母:a、b、c、d,冒号(:)被放在了字母b后面,因为b选项需要一个参数值,当getopt命令运行时,它会检查提供的参数列表

( -a  -b test1  -cd  test2  test3 ),并基于提供的optstring进行解析。注意,它会自动将-cd 选项分成两个单独的选项,并插入双破折线来分割行中的额外参数

如果指定了一个不在optstring中的选项,默认情况下,getopt会产生一条错误消息。

例如: $ getopt   ab:cd   -a  -b  test1   -cde   test2 test3 

        9.2 在脚本中使用getopt

              set  -- $( getopt -q  ab:cd  "[email protected]" )

             双破折线是set命令的的选项之一,它会将命令行参数替换成set命令的命令行值,然后该方法会将原始脚本的命令行参数传给getopt命令,之后再将getopt命令的输出传给set命令,用getopt格式化后的命令行参数来替换原始的命令行参数。

shell脚本学习五(处理用户输入)
shell脚本学习五(处理用户输入)

               getopt命令并不擅长处理带空格和引号的参数值,它会将空格当做参数分隔符,而不是根据双引号将两者当做一个参数,我们可以使用getopts来解决这个问题。

 10、使用getopts命令

               每次调用getopts命令时,它一次只处理命令行上检测到的一个参数,处理完所有的参数后,他会推出并返回一个大于0的退出状态码,这让他非常适合用解析命令行所有参数的循环中。

                 getopts   optstring   variable   

                 有效的选项字母都会列在optstring 中,如果选项字母要求有个参数值,就加一个冒号。要去掉错误消息的话,可以在optstring 之前加一个冒号。getopts命令将当前参数保存在命令行中定义的variable中。

                 getopts命令会用到两个环境变量,如果选项需要跟一个参数值,OPTARG环境变量就会保存这个值,OPTIND环境变量保存了参数列表中getopts 正在处理的参数位置,这样你就能在处理完选项之后继续处理其他命令行参数了。

shell脚本学习五(处理用户输入)

        while语句定义了getopts命令,指明了要查找哪些命令行选项,以及每次迭代中存储它们的变量名(opt),getopts命令解析命令行选项时会移除开头的单破折线( 即运行脚本时的命令行参数的-a等。。),所以在case定义中不用单破折线

shell脚本学习五(处理用户输入)

               getopts对新手来说有几个好用的功能

              ①可以在参数值中包括空格

shell脚本学习五(处理用户输入)

               ②可以将选项字母和参数值放在一起使用,而不用加空格

shell脚本学习五(处理用户输入)

              ③除此之外getopts还能够将命令行上找到的所有未定义的选项统一输出成问号

shell脚本学习五(处理用户输入)
shell脚本学习五(处理用户输入)

           getopts命令知道何时停止处理选项,并将参数留给你处理。在getopts处理每个选项时,它会将OPTIND环境变量值增一,在getopts完成处理时,你可以使用shift命令和OPTIND值来移动参数。

shell脚本学习五(处理用户输入)
shell脚本学习五(处理用户输入)

         现在你就拥有了一个能在所有shell脚本中使用的全功能命令行选项和参数处理工具

常用的linux命令选项 :

选项

描述

-a

显示所有对象

-c

生成一个计数

-d

指定一个目录

-e

扩展一个对象

-f

指定读入数据的文件

--help

显示命令的帮助信息

-i

忽略文本大小写

-l

产生输出的长格式文本

-n

使用非交互模式(批处理)

-o

将所有输出重定向到的指定的输出文件

-q

以安静模式运行

-r

递归的处理目录和文件

-s 

以安静模式运行

-v

生成详细输出

-x

排除某个对象

-y

对所有问题回答yes

 11、获得用户输入

            11.1  基本的读取

                  read命令从标准输入(键盘)或另一个文件描述符中接受输入。在收到输入后,read命令会将数据放进一个变量。

shell脚本学习五(处理用户输入)
shell脚本学习五(处理用户输入)

             此处的echo 使用了 -n选项,该选项不会在字符串末尾输出换行符,允许脚本用户紧跟其后输入数据,而不是下一行,这让脚本看起来更像表单

             实际上,read  的选项 -p 也允许直接在read命令行指定提示符

shell脚本学习五(处理用户输入)

shell脚本学习五(处理用户输入)

             read命令会将提示符后输入的所有数据分配给单个变量,要么你就指定多个变量,输入的每个数据值都会分配给变量列表的下一个变量,如果变量数量不够,剩下的数据就全部分配给最后一个变量

             在read命令行中也可以不指定变量,如果是这样,read命令会将它收到的任何数据都放进特殊环境变量REPLY中,REPLY环境变量会保存输入的所有数据,可以在shell脚本中像其他变量一样使用

           11.2  超时

              使用read命令时脚本很可能会一直苦等着脚本用户的输入,如果不管是否有数据输入,脚本都必须继续执行,你可以使用  - t  选项来指定一个计时器,-t 选项指定了read 命令等待输入的秒数,当计时器过期后,read命令会返回一个非零退出状态码

shell脚本学习五(处理用户输入)
shell脚本学习五(处理用户输入)

              如果计时器过期,read命令会以非零退出状态码退出,可以使用if - then 或 while 循环这种标准的结构化语句来理清所发生的具体情况,在本例中,计数器过期时,if语句不成立,shell会执行else部分的命令

                也可以让read命令来统计输入的字符数,当输入的字符达到预设的字符数时,就自动退出,将输入的数据赋给变量

shell脚本学习五(处理用户输入)
shell脚本学习五(处理用户输入)

              本例中将-n 选项和值1一起使用,告诉read命令在接受单个字符后退出,只要按下单个字符回答后,read命令就会接受输入并将它传给变量,无需按回车键

              11.3  隐藏方式读取

               有时候你需要从脚本用户处获得输入,但是又不能在屏幕上显示输入信息,典型的例子就是输入密码,除此之外还有很多其他需要隐藏的数据类型。

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

shell脚本学习五(处理用户输入)
shell脚本学习五(处理用户输入)

             11.4   从文件读取

                   也可以用read命令来读取linux系统上文件里保存的数据,每次调用read命令,它都会从文件中读取一行文本,当文件在没有内容时,read命令会退出并返回非零退出状态码。

                   最常见的搭配是对文件使用cat 命令 ,将结果通过管道直接传给含有read命令的while 命令

shell脚本学习五(处理用户输入)
shell脚本学习五(处理用户输入)
                 while循环会持续通过read命令处理文件中的行,直到read命令以非零退出状态码退出。