Linux-Shell交互
背景
此前讲述的一直都是Shell脚本中的内容,并没有涉及到脚本与人之间的交互,本文主要对Shell交互部分的内容做了一些笔记,内容参考于《Linux命令行与Shell编程大全》
内容
命令行传参
在shell中,如果需要向脚本中传递参数,有两种方式,一种是通过脚本运行期间的交互进行输入,还有一种是直接在启动脚本时就将对应的参数就传递给脚本,先对第二种方案进行描述,其传递的格式如下:
1 | var表示传递的参数 |
此时,对于run.sh脚本而言,它会接受到命令行传递的参数,并且将其依次记录在变量:$1 ~ $9
中,当然,如果传递的参数超过了9个,则可以通过${10}
的方式再次获取传递的其他参数,譬如:
1 | total=$[ $1 * ${11} ] |
不过,如果传递的参数内容中有空格,则需要用单引号/双引号对其进行包裹,否则shell会将其解读为多个参数。比如:
1 | ./run.sh "shuai qi de boy" |
你可以会有疑问,$0
呢?$0
其实表示脚本本身,它记录的是脚本的路径+名称
1 | echo "the file is $0" |
然后你会得到这样的结果:
1 | the file is /Users/wuxiang/Desktop/run.sh |
很显然不是我们想要的结果,我们只是想要脚本的名称,此时可以借助basename
这个命令:
1 | name=$( basename $0 ) |
这个时候的结果就正常了:
1 | the file is run.sh |
但是这里也有一点需要说明:当脚本中使用了参数变量,但是运行的时候并没有传递参数,则脚本报错,因此需要注意
.
对于脚本而言,有时候需要记录脚本运行的时候一共传递了多少参数,则可以通过参数$#
来访问:
1 | 无参数则为0 |
此外就要讲到两个特殊的变量:$*、$@
,它们都能直接访问脚本运行时传递的所有参数:
1 | $*:将所有的参数当做一个字符串记录 |
通过$*、$@
遍历的方式固然比较友好,但是它对于-var value
格式的参数就没法很好的适应了,此时可以使用shift
命令,它可以根据相对位置获取对应的参数或值
1 | 每执行一次shift,输入参数就会去掉最左边的一个参数值,并且去除的参数无法恢复 |
同样,你也可以直接指定左移指定数目的参数值:shift num
。比如:
1 | 每执行一次shift,输入参数就会去掉最左边的一个参数值,并且去除的参数无法恢复 |
如果需要获取参数对应的参数值,则可以
1 | while [ -n "$1" ] |
但是上面的方式在遇到-ac
这样的情况的时候,就没法好好的工作了,解决它的办法可以使用:getopt命令
,它的格式如下:
1 | optstring:是对应的参数简写,如果某个参数需要带值,则在其后追加: |
当getopt遇到未定义的参数名时,则其会出现报错,如果想忽视这样的报错,可以使用-q参数
,比如。
1 | getopt -q ab:cd -acd -b shuai test1 test2 |
但是如果我们想将 getopt
的输出结果直接用在shell脚本中,则还需要使用set
进行一遍转化,转化方式如下:
1 | --:是必须的,是set的参数 |
转化后,shell脚本的其他内容均无需再变,可以直接使用,比如:
1 | set -- $( getopt ab:cd "$@" ) |
不过getopt
方法并不适用于处理带空格的参数,因为其会直接将空格当成参数的间隔符号,即便是给这样的参数值加上双引号/单引号也不起作用。所以就引出了更高级一些的命令:getopts
,它的格式如下:
1 | getopts optstring variable |
如果optstring
中某个参数需要值,则在参数后追加:
,比如:
1 | getopts ab:c opt |
getopts对于未定义的参数名,也会出现报错,如果想忽略这样的报错则在optstring
前追加:
1 | getopts :ab:c opt |
getopts与getopt看似类似,但是实现逻辑不一样,大抵如下:
getopt
本质只是将命令行的参数进行规范化,但如果需要提取,本质还是需要对每个变量进行遍历判断。而getopts
则不然,它每次只取一个命令行参数,并且对非optstring
的内容直接跳过,减少了无用的内容判断。getopt
中参数和值的提取,需要通过变量$1、$2
,而在getopts
中则直接通过访问变量$variable
获取参数名,通过$OPTARG
获取参数值getopt
需要set命令进行转化,而getopts
直接可以循环遍历
举个例子如下:
1 | 当getopts循环结束时,它会返回一个大于0的状态码 |
仔细观察会发现,在getopts
循环中,是不需要shift
就可以安然的遍历所有的参数和值的,并且它支持空格间隔的参数值了。
除此之外,getopts
在每次遍历的时候还会记录两个特殊的变量:$OPTARG
、$OPTIND
,如果对应的参数有参数值,则直接使用$OPTARG
便可以获取,每次循环时,getopts会记录当前的位置$OPTIND
(数字)。
1 | while getopts ab:c opt |
输入性传参
还有一种传入参数的方式就是在shell运行过程中传递的参数,这种就需要借助命令:read
,read最简单的方式就是:
1 | 它会等待用户的输入,然后将输入的结果赋值给variable |
如果想要给输入的内容前加上一句友好的提示,则可以使用参数:-p
:
1 | read -p "please inter your name: " name |
通过上述的方式,则shell终端会一直等待用户的输入,如果希望加个超时时间,则可以使用参数:-t
1 | read -p "please inter your name: " -t 10 name |
同样,如果希望用户输入指定长度的文字后就直接自动退出,并将输入的内容传递给变量,则可使用参数:-n
1 | read -p "please inter your name: " -t 10 -n 10 name |
也可以针对输入的加密内容不显示,可以使用参数:-s
1 | read -p "please inter your name: " -s name |
然后就是通过read读取文件,但是需要借助cat
命令,或者输入重定向。它一次性只读取一行内容,因此要获取全部内容的话,则可以通过循环,
1 | cat "file.txt" | while read line |