由于我平时的工作环境是linux,所以无可避免的经常使用命令行模式和shell脚本,而且有些命令行每天都要输好多遍,比如ssh登录之类的,所以干脆把平时常用的命令都写成脚本文件,所以特意开了一个shell脚本的分类,用来记录学习shell的过程,以便温习。
- 首先我们从一个简单的脚本来开启shell学习的大门,假设你想要知道当前系统中有多少人登录,可以使用 who 命令来查询:
1 $ who 2 george pts/2 Dec 31 16:39 3 betsy pts/3 Dec 27 11:07
- 但如果在多用户系统上信息量会很大,在统计时很麻烦,所以我们可以使用通道和wc 程序来统计行数(line)、字数(word)与字符数(character),本例中为统计登录人数所以查询行数即可。
1 $ who | wc -l 2 2
- 注意:| (管道)符号可以在两个程序之间建立管道:即who 的输出变成了wc 的输入
- 接下来就可以将其转变为一个小型的脚本文件,将上述命令写入一个一般文本文件中,然后赋予执行权限执行即可,这也展现了脚本文件的开发周期,可以先在命令行进行测试开发,无误后写入文件.
1 $ vi wc.sh 2 #进入文本编辑模式,将命令who | wc -l写入,保存退出 3 $ chmod +x wc.sh #赋予该脚本文件执行权限 4 $ ./wc.sh #执行脚本 5 $ 2 #获得输出结果
- 在很多脚本的第一行都会有#! 这两个字符,这两个字符的含义是告知linux内核应该以哪种shell来执行当前脚本,当前大多数脚本都是使用#!/bin/sh ,也有使用#!/bin/csh (是C shell的解释器)
1 $ cat wc.sh 2 3 #!/bin/sh 4 who | wc -l
- 分号; 可用来分割同一行里的多条命令,Shell会依次执行的,如果使用了& 符号,则代表当前命令是后台执行,即不需要等到当前命令执行完毕就可以继续执行下一条命令
- 变量:Shell变量的名称的开头是一个字母或者下划线符号,后面可以接任意长度的字母、数字和下划线符号,并且变量长度没有限制;变量赋值的方式为:先写变量名称,紧接着= 字符,最后是赋予的值,中间没有空格,当你想取用变量的值则需要在变量的名称前使用$ 字符。
1 $ value=this_is_a_long_value #当赋予的值中存在空格时,需要引号括起来 2 $ echo $value 3 $ this_is_a_long_value
- 输出命令:大多数人可能习惯使用echo命令来进行简单的输出,但要知道echo是由版本差异的,所以移植是一个可能存在风险的问题,相对来看,还是比较推荐使用printf命令,printf命令几乎完全把c里的printfcopy下来,所以c中的格式化字符也同样适用的。
1 $ printf "hello world.\n" # printf不会像echo那样隐式添加一个换行符,所以需要手动添加换行符\n 2 $ printf “The first program always prints %s %s.\n” Hello World
- 重定向:以< 改变标准输入,以 > 改变标准输出
1 program < file 可以将program的标准输入修改为file 2 eg. tr -d ‘\r’ < test.file #这条命令会将test.file文件中的回车符删除掉 3 4 program > file 可以将program的标准输出修改为file 5 eg. tr -d ‘\r’ < test.file > result.file #这条命令会先将test.file中的回车删除,再将处理完的数据输出到result.file中,但test.file中的数据不会发生改变 6 7 #注意:> 重定向符在目的文件不存在时会自动新建一个,如果文件已存在则会覆盖原有数据,如果希望追加数据,则需要使用 >> 重定向符
- 以| 符号建立通道
1 program1 | program2 #program2可以将program1的标准输出作为自己的输入
特殊文件 /dev/null 和/dev/tty
1 #linux系统提供了两个对Shell编程特别有用的特殊文件 2 #/dev/null文件 3 #该文件一般被称为位桶。传送到此文件中的数据都会被系统丢掉,也就是说当程序将数据写入次文件时,从结果上看已经成功写入数据了,但实际上却什么事都没做 4 #例如测试一个文件是否包含某个模式 5 if grep pattern myfile > /dev/null 6 then 7 printf “find.” 8 else 9 printf ”don’t find” 10 fi 11 12 #/dev/tty 13 #当程序打开此文件时,Linux会自动将它重定向到一个终端再与程序结合 14 eg.printf “Enter new passed:” #提示输入新密码 15 stty -echo #关闭自动打印输入字符的功能 16 read pass < /dev/tty #从当前终端读取密码 17 printf “Enter again:” #再次输入密码 18 read pass2 < /dev/tty 19 stty echo #打开自动打印输入字符的功能
- stty命令迎来控制终端的各种设置,-echo选项为关闭自动打印每个输入字符的功能,echo选项则是打开该功能
- 在相对复杂的shell脚本中可以使用set -x 来打开代码追踪功能,使用set +x 来关闭该功能,开启该功能后的代码中,凡是执行过的都会在该行首部添加一个+ 号
1 #!/bin/sh 2 set -x #开启代码追踪功能 3 value=1 4 if [ “$value”x = “0”x ];then #此处在值后面加一个x是规避值为空的情况 5 printf “value is 0.\n” 6 else 7 printf “value isn’t 0.\n” 8 fi 9 set +x #关闭代码追踪功能
- 输出结果为:
1 + value=1 2 + if [ “$value”x = “0”x ];then 3 printf “value is 0.\n” #由于value的值不为0,所以没有执行这句话,所以首部没有+符号 4 + else 5 + printf “value isn’t 0.\n” 6 + fi 7 + set +x