前言
本篇笔记的参考资料是(《Linux命令行与shell脚本编程大全》(第3版),外加百度辅助,本篇笔记主要内容是Shell脚本的一些基本知识。
使用命令行的一大特点就是能够写脚本,可以将一些命令写到一个脚本中,自动运行。而在Linux的命令行中,一次基本上只能运行一个或几个命令,就像下面的这样,它可以运行两个命令,只是要用分号隔开。
|
|
这两个命令其实也可以视为一个非常简单的脚本,虽然它只有两个命令,作用就是显示今天的日期以及当前登录到系统中的用户。
创建shell脚本文件
如果要将shell命令放到文本文件中,就需要一个文本编辑器,Linux中常用的是vim,写好的脚本文件如下所示:
|
|
将脚本文件保存,命令为test.sh。
现在解释一下这个脚本:
第1行:写入的是#!/bin/bash
,#号是用于注释的,shell并不会处理注释,注释只是起到说明的作用,但第1行是个例外,#!的意思是要告诉shell要到哪个shell来运行,这里指定的是bash。
第2行:在第1行中指定了运行脚本的shell后,就可以输入命令了,输入一个命令后,回车,再输入另外一个命令,或者是用分号隔开两个命令。
命令结束后,输入脚本,如下所示:
|
|
这是因为,shell是通过PATH环境变量来查找命令的,现在test.sh这个脚本文件并不在环境变量PATH中,因此如果要运行这个脚本,只有2种方法:
第一,将shell脚本文件所在的目录添加到PATH环境中;
第二,使用绝对或相对路径引用shell脚本文件。
现在使用第二种方法,如下所示:
|
|
发现没有反应,此时输入bash test
,如下所示:
|
|
test是一个脚本文件,通过ls -lF
命令查看发现,test不是一个可执行程序,因此运行这个脚本,需要使用bash test,如果要将它设为可执行文件,则如下操作:
|
|
此时输入的是相对路径./test
,如果要直接运行,则需要将test添加到环境变量中去,如下操作:
|
|
添加到环境变量用到了echo 'export PATH=$PATH:/home/biotest/'>>~/.bashrc
命令,此外,还有一点,test是用shell写的,原来没有后缀名,输入后无法运行,当添加上上了.sh
后,可以正常运行,原理现在还不清楚,懂了再写。
显示消息
多数shell都会产生自己的输出,这些输出会显示脚本所运行的控制台显示器上。很多时候,在自己写脚本时,要添加自己的文本消息来告诉脚本用户正在做什么,需要echo命令,如果在echo命令后面加上一个字符串,就会显示出这个文本字符串,如下所示:
|
|
从中可以发现:第一,常规情况下字符串并不需要使用引号;第二,如果要使用引号,字符串中间的引号不能与字符串两端的引号重复(即字符串中使用单引号,整个字符串就使用双引号,反之亦然)。
再看一案例,新建一个文件,命名为test1,输入以下代码:
|
|
结果如下所示:
使用变量
环境变量是常见的变量之一,在shell脚本中,也能使用环境变量,只需要在环境㸄前加上美元符号($)即可,下面的脚本中就使用了一些环境变量,如下所示:
运行后结果如下:
|
|
如果在字符串中使用美元符号,如下所示:
|
|
这里面的美元符号就不会显示,如果要显示的话,需要添加转义字符,如下所示:
|
|
用户变量
用户变量是用户自己定义的一些变量,这些常见的编程语言中的变量大同小异,看下面的案例:
|
|
运行后结果如下所示:
|
|
有关美元符号与赋值的另一案例
如果引用变量不使用美元符号,会将引用的某个变量名称识别为字符串,看下面的案例:
|
|
结果如下所示:
从结果可以看出来,当value2=$value1时,就把变量value1的值10赋值给了value2,当使用value3=value1时,由于没加美元符号,就把value1这个字符串赋值给了value3。
命令替换
shell脚本有一个重要的功能就是从命令输出中提取信息,并将值赋给某个变量。有2种方法可以将命令输出赋值给某个变量:
第一:使用反引号(`);
第二:使用$()
格式。
使用这两种方法可以使shell命令的输出赋值给变量,具体用法如下所示:
|
|
具体的案例如下所示:
运行结果如下所示:
|
|
第二案例:
以下的案例就是就是通过命令替换获得当前日期,并用它来生成唯一文件名。
|
|
运行后没有输出信息,但是它会在当前目录下生成一个log文件,名称就是log加上今天的日期(今天是2018年4月27日),则这个文件名称就是log.180427。代码的运行原理是,date命令得到当前日期,经格式化后,赋值给today。关于日期的格式化,可以看下面的案例:
|
|
重定向输入和输出
有时候我们会遇到这样的场景,我想把某个命令的输出结果保存到某个文件中,这个文件我可以用于查看,或者是经后来的命令处理。这就用到了重定向,重定向可以用于输入,也可以用于输出。
输出重定向
最基本的重定向就是将命令的输出发送到一个文件中,bash shell中使用大于号(>)来完成,格式为command > outputfile
,如下所示:
|
|
使用重定向文件创建了一个文件test7,将date命令的输出结果重定向了到了test7中,如果这个文件存在,则重定向的数据会覆盖原来的数据,如果不想覆盖,只是追加,可以使用双大于号。
输入重定向
常规的输入重定向
输入重定向和输出重定向正好相反。输入重定向将文件的内容重定向到命令。 输入重定向符号是小于号(<),格式为command < inputfile
。
如下所示:
在这个案例中,将test7的内容输入到wc命令中,wc命令可以对数据中的文本进行计数(wc的全称为words count),wc的默认输出有3个值,从左到右分别为:
①文本的行数;②文本的词数;③文本的字节数,在前面的案例中,结果就是2行,11个单词,73个字节。
内联输入重定向
内联输入重定向的英文是inline input redirection,这种方法无需使用文件进行重定向,只需要在命令行中指定用于输入重定向的数据就可以了。内联输入重定向符号是远小于号(<<)。除了这个符号,必须指定一个文本标记来划分输入数据的开始和结尾。任何字符串都可作为文本标记,但在数据的开始和结尾文本标记必须一致,格式为:
maker是数据的开始,也是结果,data是位于maker之间的文本文件,看一个案例:
当输入wc << EOF时,命令行会自动变成大于号,接着输入内容,输入完毕后,再输入EOF表示结束,此时命令开始运行,结果为3,9, 42.
管道
管道的使用场景为,将命令A的输出结果导入到命令B,使A的结果成为B的输入。其实这样可以通过重定向实现,但是太麻烦,管道就是出于此目的而设计的。
举个例子:统计当前的文件数有多少个。
先看一下重定向是如何实现的:
使用重定向就是,先用ls列出当前的文件名,重定向到filename文件,然后使用wc命令来统计。
再看一下管道命令:
管道命令通过一条竖线,将ls的结果导入到wc中。
退出脚本
shell中运行的每个命令都是使用退出状态码(exit status)告诉shell它已经运行完毕,退出状态码是一个0~255的号数值,在命令结束运行时,由命令传给shell。
查看退出状态码
Linux提供了一个专门的变量$?
来保存上个已执行命令的退出状态码。对于需要进行检查的 命令,必须在其运行完毕后立刻查看或使用 $? 变量。它的值会变成由shell所执行的最后一条命令的退出状态码。
|
|
通常一个成功结束的命令的退出状态码是0,如果命令结束时有错误,这个代码就是一个正整数,如下所示:
|
|
exit命令
exit 命令允许你在脚本结束时指定一个退出状态码,如下所示:
|
|
运行后,结果如下所示: