19 Linux-Shell编程
19.1 正则表达式
19.1.1 概述
而在系统当中搜索文件的命令,如ls、find、cp这些命令不支持正则表达式,所以只能使用shell自己的通配符来进行匹配了。
19.1.2 基础正则表达式
| 元字符 | 作用 |
|---|---|
| * | 前一个字符匹配0次或任意多次。 |
| . | 匹配除了换行符外任意一个字符。 |
| ^ | 匹配行首。例如:^hello会匹配以hello开头的行。 |
| $ | 匹配行尾。例如:hello&会匹配以hello结尾的行。 |
| [] | 匹配中括号中指定的任意一个字符,只匹配一个字符。 例如:[aoeiu] 匹配任意一个元音字母,[0-9] 匹配任意一位数字,[a-z] [0-9]匹配小写字和一位数字构成的两位字符 |
| [^] | 匹配除中括号的字符以外的任意一个字符。例如:[^0-9] 匹配任意一位非数字字符,[^a-z] 表示任意一位非小写字母。 |
| \ | 转义符。用于取消讲特殊符号的含义取消。 |
| \{n\} | 表示其前面的字符恰好出现n次。例如:[0-9]{4} 匹配4位数字, |
| \{n,\} | 表示其前面的字符出现不小于n次。例如: [0-9]{2,} 表示两位及以上的数字。 |
| \{n,m\} | 表示其前面的字符至少出现n次,最多出现m次。例如: [a-z]{6,8} 匹配6到8位的小写字母。 |
在~/.bashrc文件中建立这个别名:
1)练习文件建立
2)“*”前一个字符匹配0次,或任意多次
如果这样写正则表达式“aa*”代表这行字符串一定要有一个a,但是后面有没有a都可以。也就是说会匹配至少包含有一个a的行:
如果正则表达式是“aaa*”,则会匹配最少包含两个连续a的字符串,如:
如果正则表达式是“aaaaa*”,则会匹配最少包含四个个连续a的字符串,如:
当然如果再多写一个a,如“aaaaaa*”就不能从这篇文档中匹配任何内容了,因为我们这篇文档中a最多的单词“actuaaaally”只有四个个连续的a,而“aaaaaa*”会匹配最少五个连续的a。
3) “.” 匹配除了换行符外任意一个字符
正则表达式“.”只能匹配一个字符,这个字符可以是任意字符,举个例子:
4)“^”匹配行首,“$”匹配行尾
“^”代表匹配行首,比如“^M”会匹配以大写“M”开头的行:
“$”代表匹配行尾,如果“n$”会匹配以小写“n”结尾的行:
而“^$”则会匹配空白行:
5) “[]” 匹配中括号中指定的任意一个字符,只匹配一个字符
“[]”会匹配中括号中指定任意一个字符,注意只能匹配一个字符。比如[ao]要不会匹配一个a字符,要不会匹配一个o字符:
而“[0-9]”会匹配任意一个数字,如:
而“[A-Z]”则会匹配一个大写字母,如:
如果正则是“^[a-z]”代表匹配用小写字母开头的行:
6)“[^]” 匹配除中括号的字符以外的任意一个字符
而“^[^a-zA-Z]”则会匹配不用字母开头的行:
7) “\” 转义符
8)“{n}”表示其前面的字符恰好出现n次
上面的两行都包含三个连续的a,所以都会匹配。但是如果先要只显示三个连续的a,可以这样来写正则:
如果正则是“[0-9]{3}”则会匹配包含连续的三个数字的字符串:
虽然“5555”有四个连续的数字,但是包含三个连续的数字,所以也是可以列出的。可是这样不能体现出来“[0-9]{3}”只能匹配三个连续的数字,而不能匹配四个连续的数字。那么正则就应该这样来写“^[0-9]{3}[a-z]”:
9) “{n,}”表示其前面的字符出现不小于n次
“{n,}”会匹配前面的字符出现最少n次。比如“zo{3,}m”这个正则就会匹配用z开头,m结尾,中间最少有三个o的字符串。那么“^[0-9]{3,}[a-z]”这个正则就能匹配最少用连续三个数字开头的字符串:
而“[su]a{3,}[il]”正则则会匹配在字母s或u和i或l之间,最少出现三个连续的a的字符串:
10)“{n,m}”匹配其前面的字符至少出现n次,最多出现m次
19.1.3 扩展正则表达式
熟悉正则表达式的童鞋应该很疑惑,在正则表达式中应该还可以支持一些元字符,比如“+”“?”“|”“()”。其实Linux是支持这些元字符的,只是grep命令默认不支持而已。如果要想支持这些元字符,必须使用egrep命令或grep -E选项,所以我们又把这些元字符称作扩展元字符。
如果查询grep的帮助,对egrep的说明就是和grep -E选项一样的命令,所以我们可以把两个命令当做别名来对待。通过下表来看看Shell中支持的扩展元字符:
| 扩展元字符 | 作用 |
|---|---|
| + | 前一个字符匹配1次或任意多次。 如“go+gle”会匹配“gogle”、“google”或“gooogle”,当然如果“o”有更多个,也能匹配。 |
| ? | 前一个字符匹配0次或1次。 如“colou?r”可以匹配“colour”或“color”。 |
| | | 匹配两个或多个分支选择。 如“was|his”会匹配既包含“was”的行,也匹配包含“his”的行。 | | () | 匹配其整体为一个字符,即模式单元。可以理解为由多个单个字符组成的大字符。 如“(dog)+”会匹配“dog”、“dogdog”、“dogdogdog”等,因为被()包含的字符会当成一个整体。但“hello (world|earth)”会匹配“hello world”及“hello earth”。 |
19.2 字符截取和替换命令
19.2.1 cut列提取命令
cut命令的默认分隔符是制表符,也就是“tab”键,不过对空格符可是支持的不怎么好啊。我们先建立一个测试文件,然后看看cut命令的作用吧:
那如果想要提取多列呢?只要列号直接用“,”分开,命令如下:
cut可以按照字符进行提取,需要注意“8-”代表的是提取所有行的第十个字符开始到行尾,而“10-20”代表提取所有行的第十个字符到第二十个字符,而“-8”代表提取所有行从行首到第八个字符:
如果我想用cut命令截取df命令的第一列和第三列,就会出现这样的情况:
19.2.2 awk编程
1)概述
AWK 是一种处理文本文件的语言,是一个强大的文本分析工具。
之所以叫 AWK 是因为其取了三位创始人 Alfred Aho,Peter Weinberger, 和 Brian Kernighan 的 Family Name 的首字符。
2)printf格式化输出
为了演示printf命令,我们需要修改下刚刚cut命令使用的student.txt文件,文件内容如下:
我们使用printf命令输出下这个文件的内容:
晕菜,全变乱了一锅粥。这就是printf命令,如果不指定输出格式,则会把所有输出内容连在一起输出。其实文本的输出本身就是这样的,cat等文本输出命令之所以可以按照格式漂亮的输出,那是因为cat命令已经设定了输出格式。那么为了用printf输出合理的格式,应该这样做:
如果不想把成绩当成字符串输出,而是按照整型和浮点型输出,则要这样:
3)awk基本使用
我们这里先来学习awk基本用法,也就是只看看格式化输出动作是干什么的。至于条件类型和流程控制语句我们在后面再详细介绍。那看看这个例子吧:
比如刚刚截取df命令的结果时,cut命令已经力不从心了,我们来看看awk命令:
4) awk的条件
| 条件的类型 | 条件 | 说明 |
|---|---|---|
| awk保留字 | BEGIN | 在awk程序一开始时,尚未读取任何数据之前执行。 BEGIN后的动作只在程序开始时执行一次 |
| awk保留字 | END | 在awk程序处理完所有数据,即将结束时执行。 END后的动作只在程序结束时执行一次 |
| 关系运算符 | > | 大于 |
| 关系运算符 | < | 小于 |
| 关系运算符 | >= | 大于等于 |
| 关系运算符 | <= | 小于等于 |
| 关系运算符 | == | 等于。用于判断两个值是否相等,如果是给变量赋值,请使用“=”号 |
| 关系运算符 | != | 不等于 |
| 关系运算符 | A~B | 判断字符串A中是否包含能匹配B 表达式的子字符串 |
| 关系运算符 | A!~B | 判断字符串A中是否不包含能匹配B表达式的子字符串 |
| 正则表达式 | /正则/ | 如果在“//”中可以写入字符,也可以支持正则表达式 |
-
BEGIN
BEGIN是awk的保留字,是一种特殊的条件类型。BEGIN的执行时机是“在awk程序一开始时,尚未读取任何数据之前执行”。一旦BEGIN后的动作执行一次,当awk开始从文件中读入数据,BEGIN的条件就不再成立,所以BEGIN定义的动作只能被执行一次。例如:
加入了条件之后,只有条件成立动作才会执行,如果条件不满足,则动作则不运行。通过这个实验,大家可以发现,虽然awk是列提取命令,但是也要按行来读入的。这个命令的执行过程是这样的:
1) 如果有BEGIN条件,则先执行BEGIN定义的动作
2) 如果没有BEGIN条件,则读入第一行,把第一行的数据依次赋予$0、$1、$2等变量。其中$0代表此行的整体数据,$1代表第一字段,$2代表第二字段。
3) 依据条件类型判断动作是否执行。如果条件符合,则执行动作,否则读入下一行数据。如果没有条件,则每行都执行动作。
4) 读入下一行数据,重复执行以上步骤。
再举个例子,如果我想看看Sc用户的平均成绩呢:
当使用df命令查看分区使用情况是,如果我只想查看真正的系统分区的使用状况,而不想查看光盘和临时分区的使用状况,则可以:
5)awk内置变量
| awk内置变量 | 作 用 |
|---|---|
| $0 | 代表目前awk所读入的整行数据。我们已知awk是一行一行读入数据的 $0就代表当前读入行的整行数据。 |
| $n | 代表目前读入行的第n个字段。 |
| NF | 当前行拥有的字段(列)总数。 |
| NR | 当前awk所处理的行,是总数据的第几行。 |
| FS | 用户定义分隔符。awk的默认分隔符是任何空格, 如果想要使用其他分隔符(如“:”),就需要FS变量定义。 |
| ARGC | 命令行参数个数。 |
| ARGV | 命令行参数数组。 |
| FNR | 当前文件中的当前记录数(对输入文件起始为1)。 |
| OFMT | 数值的输出格式(默认为%.6g)。 |
| OFS | 输出字段的分隔符(默认为空格)。 |
| ORS | 输出记录分隔符(默认为换行符)。 |
| RS | 输入记录分隔符(默认为换行符)。 |
这里“:”分隔符生效了,可是第一行却没有起作用,原来我们忘记了“BEGIN”条件,那么再来试试:
如果我只想看看sshd这个伪用户的相关信息,则可以这样使用:
6)awk流程控制
我们再来利用下student.txt文件做个练习,后面的使用比较复杂,我们再看看这个文件的内容:
我们先来看看该如何在awk中定义变量与调用变量的值。假设我想统计PHP成绩的总分,那么就应该这样:
我们解释下这个命令。“NR==2{php1=$3}”(条件是NR==2,动作是php1=$3)这句话是指如果输入数据是第二行(第一行是标题行),就把第二行的第三字段的值赋予变量“php1”。“NR==3{php2=$3}”这句话是指如果输入数据是第三行,就把第三行的第三字段的值赋予变量“php2”。
“NR==4{php3=$3;totle=php1+php2+php3;print "totle php is " totle}”(“NR==4”是条件,后面{}中的都是动作)这句话是指如果输入数据是第四行,就把第四行的第三字段的值赋予变量“php3”;然后定义变量totle的值是“php1+php2+php3”;然后输出“totle php is”关键字,后面加变量totle的值。
在awk编程中,因为命令语句非常长,在输入格式时需要注意以下内容:
-
多个条件{动作}可以用空格分割,也可以用回车分割。
-
在一个动作中,如果需要执行多个命令,需要用“;”分割,或用回车分割。
-
在awk中,变量的赋值与调用都不需要加入“$”符。
-
条件中判断两个值是否相同,请使用“==”,以便和变量赋值进行区分。
在看看该如何实现流程控制,假设如果Linux成绩大于90,就是一个好男人(学PHP的表示压力很大!):
其实在awk中if判断语句,完全可以直接利用awk自带的条件来取代,刚刚的脚本可以改写成这样:
7)awk函数
awk编程也允许在编程时使用函数,在本小节我们讲讲awk的自定义函数。awk函数的定义方法如下:
我们定义一个简单的函数,使用函数来打印student.txt的学员姓名和平均成绩,应该这样来写函数:
8)awk中调用脚本
对于小的单行程序来说,将脚本作为命令行自变量传递给awk是非常简单的,而对于多行程序就比较难处理。当程序是多行的时候,使用外部脚本是很适合的。首先在外部文件中写好脚本,然后可以使用awk的-f选项,使其读入脚本并且执行。 例如,我们可以先编写一个awk脚本:
然后可以使用“-f”选项来调用这个脚本:
19.2.3 sed命令
sed主要是用来将数据进行选取、替换、删除、新增的命令,我们看看命令的语法:
对sed命令大家要注意,sed所做的修改并不会直接改变文件的内容(如果是用管道符接收的命令的输出,这种情况连文件都没有),而是把修改结果只显示到屏幕上,除非使用“-i”选项才会直接修改文件。
-
行数据操作
闲话少叙,直奔主题,我们举几个例子来看看sed命令到底是干嘛的。假设我想查看下student.txt的第二行,那么就可以利用“p”动作了:
好像看着不怎么顺眼啊!“p”命令确实输出了第二行数据,但是sed命令还会把所有数据都输出一次,这时就会看到这个比较奇怪的结果。那如果我想指定输出某行数据,就需要“-n”选项的帮助了:
再来看看如何删除文件的数据:
再来看看如何追加和插入行数据:
“a”会在指定行后面追加入数据,如果想要在指定行前面插入数据,则需要使用“i”动作:
如果是想追加或插入多行数据,除最后一行外,每行的末尾都要加入“\”代表数据未完结。再来看看“-n”选项的作用:
“-n”只查看sed命令操作的数据,而不是查看所有数据。 再来看看如何实现行数据替换,假设李明老师的成绩太好了,我实在是不想看到他的成绩刺激我,那我就可以这样:
sed命令默认情况是不会修改文件内容的,如果我确定需要让sed命令直接处理文件的内容,可以使用“-i”选项。不过要小心啊,这样非常容易误操作,在操作系统文件时请小心谨慎。可以使用这样的命令:
替换的格式和vim非常类似,假设我觉得我自己的PHP成绩太低了,想作弊给他改高点,就可以这样来做:
这样看起来就比较爽了吧。如果我想把Tg老师的成绩注释掉,让他不再生效(没有成绩了吧?补考去吧?)。可以这样做:
在sed中只能指定行范围,所以很遗憾我在他们两个的中间,不能只把他们两个注释掉,那么我们可以这样:
“-e”选项可以同时执行多个sed动作,当然如果只是执行一个动作也可以使用“-e”选项,但是这时没有什么意义。还要注意,多个动作之间要用“;”号或回车分割,例如上一个命令也可以这样写:
19.3 字符处理命令
19.3.1 排序命令sort
sort命令默认是用每行开头第一个字符来进行排序的,比如:
如果想要反向排序,请使用“-r”选项:
如果想要指定排序的字段,需要使用“-t”选项指定分隔符,并使用“-k”选项指定字段号。加入我想要按照UID字段排序/etc/passwd文件:
看起来好像很美,可是如果仔细看看,怎么daemon用户的UID是2,反而排在了下面?这是因为sort默认是按照字符排序,前面用户的UID的第一个字符都是1,所以这么排序。要想按照数字排序,请使用“-n”选项:
当然“-k”选项可以直接使用“-k 3”,代表从第三字段到行尾都排序(第一个字符先排序,如果一致,第二个字符再排序,知道行尾)。
19.3.2 uniq
uniq命令是用来取消重复行的命令,其实和“sort -u”选项是一样的。命令格式如下:
19.3.3 统计命令wc
19.4 条件判断
19.4.1 按照文件类型进行判断
根据下表,我们先来看看test可以进行哪些文件类型的判断:
| 测试选项 | 作用 |
|---|---|
| -b 文件 | 判断该文件是否存在,并且是否为块设备文件(是块设备文件为真) |
| -c文件 | 判断该文件是否存在,并且是否为字符设备文件(是字符设备文件为真) |
| -d 文件 | 判断该文件是否存在,并且是否为目录文件(是目录为真) |
| -e 文件 | 判断该文件是否存在(存在为真) |
| -f 文件 | 判断该文件是否存在,并且是否为普通文件(是普通文件为真) |
| -L 文件 | 判断该文件是否存在,并且是否为符号链接文件(是符号链接文件为真) |
| -p 文件 | 判断该文件是否存在,并且是否为管道文件(是管道文件为真) |
| -s 文件 | 判断该文件是否存在,并且是否为非空(非空为真) |
| -S 文件 | 判断该文件是否存在,并且是否为套接字文件(是套接字文件为真) |
还记得多命令顺序执行的“&&”和“||”吗?我们可以再判断一下/root/sh/是否是目录:
19.4.2 按照文件权限进行判断
test是非常完善的判断命令,还可以判断文件的权限,
| 测试选项 | 作用 |
|---|---|
| -r 文件 | 判断该文件是否存在,并且是否该文件拥有读权限(有读权限为真) |
| -w文件 | 判断该文件是否存在,并且是否该文件拥有写权限(有写权限为真) |
| -x 文件 | 判断该文件是否存在,并且是否该文件拥有执行权限(有执行权限为真) |
| -u 文件 | 判断该文件是否存在,并且是否该文件拥有SUID权限(有SUID权限为真) |
| -g 文件 | 判断该文件是否存在,并且是否该文件拥有SGID权限(有SGID权限为真) |
| -k 文件 | 判断该文件是否存在,并且是否该文件拥有SBit权限(有SBit权限为真) |
比如:
19.4.3 两个文件之间进行比较
通过下表来看看如何进行两个文件之间的比较:
| 测试选项 | 作用 |
|---|---|
| 文件1 -nt 文件2 | 判断文件1的修改时间是否比文件2的新(如果新则为真) |
| 文件1 -ot 文件2 | 判断文件1的修改时间是否比文件2的旧(如果旧则为真) |
| 文件1 -ef 文件2 | 判断文件1是否和文件2的Inode号一致,可以理解为两个文件是否为同一个文件。 这个判断用于判断硬链接是很好的方法 |
我们一直很苦恼,到底该如何判断两个文件是否是硬链接呢?这时test就派上用场了:
19.4.4 两个整数之间比较
通过下表,我们来学习下字符串的判断:
| 测试选项 | 作用 |
|---|---|
| -z 字符串 | 判断字符串是否为空(为空返回真) |
| -n 字符串 | 判断字符串是否为非空(非空返回真) |
| 字串1 ==字串2 | 判断字符串1是否和字符串2相等(相等返回真) |
| 字串1 != 字串2 | 判断字符串1是否和字符串2不相等(不相等返回真) |
举个例子:
再来看看如何判断两个字符串相等:
19.4.5 字符串的判断
通过下表,来看看多重条件判断是什么样子的:
| 测试选项 | 作用 |
|---|---|
| 判断1 -a 判断2 | 逻辑与,判断1和判断2都成立,最终的结果才为真 |
| 判断1 -o 判断2 | 逻辑或,判断1和判断2有一个成立,最终的结果就为真 |
| !判断 | 逻辑非,使原始的判断式取反 |
举个例子:
再来看看如何判断两个字符串相等:
19.4.6 多重条件判断
通过下表,来看看多重条件判断是什么样子的:
| 测试选项 | 作用 |
|---|---|
| 判断1 -a 判断2 | 逻辑与,判断1和判断2都成立,最终的结果才为真 |
| 判断1 -o 判断2 | 逻辑或,判断1和判断2有一个成立,最终的结果就为真 |
| !判断 | 逻辑非,使原始的判断式取反 |
举个例子:
要想让刚刚的判断式返回真,需要给变量aa重新赋个大于23的值:
再来看看逻辑非是什么样子的:
注意:“!”和“-n”之间必须加入空格,否则会报错的。
19.5 流程控制
19.5.1 if条件判断
1)单分支if条件语句
单分支条件语句最为简单,就是只有一个判断条件,如果符合条件则执行某个程序,否则什么事情都不做。语法如下:
单分支条件语需要注意几个点:
-
if语句使用fi结尾,和一般语言使用大括号结尾不同
-
[ 条件判断式 ]就是使用test命令判断,所以中括号和条件判断式之间必须有空格
-
then后面跟符合条件之后执行的程序,可以放在[]之后,用“;”分割。也可以换行写入,就不需要“;”了,比如单分支if语句还可以这样写:
2)双分支if条件语句
示例1: 我们写一个数据备份的例子,来看看双分支if条件语句。
示例2: 再举个例子,在工作当中,服务器上的服务经常会宕机。如果我们对服务器监控不好,就会造成服务器中服务宕机了,而管理员却不知道的情况,这时我们可以写一个脚本来监听本机的服务,如果服务停止或宕机了,可以自动重启这些服务。我们拿apache服务来举例:
以我们使用nmap端口扫描命令,nmap命令格式如下:
这条命令的执行结果如下:
知道了nmap命令的用法,我们在脚本中使用的命令就是为了截取http的状态,只要状态是“open”就证明apache启动正常,否则证明apache启动错误。来看看脚本中命令的结果:
3)多分支if条件语句
那我们再写一个例子,用if多分支条件语句来判断一下用户输入的是一个文件,还是一个目录:
19.5.2 多分支case条件语句
case语句和if…elif…else语句一样都是多分支条件语句,不过和if多分支条件语句不同的是,case语句只能判断一种条件关系,而if语句可以判断多种条件关系。case语句语法如下:
这个语句需要注意以下内容:
-
case语句,会取出变量中的值,然后与语句体中的值逐一比较。如果数值符合,则执行对应的程序,如果数值不符,则依次比较下一个值。如果所有的值都不符合,则执行“)”(“”代表所有其他值)中的程序。
-
case语句以“case”开头,以“esac”结尾。
每一个分支程序之后要通过“;;”双分号结尾,代表该程序段结束(千万不要忘记,超哥每次写case语句,都会忘记双分号,有点“囧”)。我们写一个判断是“yes/no”的例子:
19.5.3 for循环
for循环是固定循环,也就是在循环时已经知道需要进行几次的循环,有时也把for循环称为计数循环。for的语法有如下两种:
这种语法中for循环的次数,取决于in后面值的个数(空格分隔),有几个值就循环几次,并且每次循环都把值赋予变量。也就是说,假设in后面有三个值,for会循环三次,第一次循环会把值1赋予变量,第二次循环会把值2赋予变量,以此类推。
语法二中需要注意:
-
初始值:在循环开始时,需要给某个变量赋予初始值,如i=1;
-
循环控制条件:用于指定变量循环的次数,如i<=100,则只要i的值小于等于100,循环就会继续;
-
变量变化:每次循环之后,变量该如何变化,如i=i+1。代表每次循环之后,变量i的值都加1。
1)语法一举例:
示例1:打印时间
示例2:批量解压缩
2)语法二举例
示例1:从1加到100
示例2:批量添加指定数量的用户
示例3:批量删除用户
19.5.4 while循环
对while循环来讲,只要条件判断式成立,循环就会一直继续,直到条件判断式不成立,循环才会停止。好吧,我们还是写个1加到100的例子吧,这种例子虽然对系统管理帮助不大,但是对理解循环非常有帮助:
19.5.5 until循环
再来看看until循环,和while循环相反,until循环时只要条件判断式不成立则进行循环,并执行循环程序。一旦循环条件成立,则终止循环。语法如下:
还是写从1加到100这个例子,注意和while循环的区别:
19.5.6 函数
那我们写一个函数吧,还记得从1加到100这个循环吗?这次我们用函数来实现它,不过不再是从1加到100了,我们让用户自己来决定加到多少吧:
19.5.7 特殊流程控制语句
1)exit语句
系统是有exit命令的,用于退出当前用户的登录状态。可是在Shell脚本中,exit语句是用来退出当前脚本的。也就是说,在Shell脚本中,只要碰到了exit语句,后续的程序就不再执行,而直接退出脚本。exit的语法如下:
如果exit命令之后定义了返回值,那么这个脚本执行之后的返回值就是我们自己定义的返回值。可以通过查询$?这个变量,来查看返回值。如果exit之后没有定义返回值,脚本执行之后的返回值是执行exit语句之前,最后执行的一条命令的返回值。写一个exit的例子:
这个脚本中,大家需要思考,如果我输入的不是数字,那么“echo "The number is: $num"”这个脚本是否会执行?当然不会,因为如果输入的不是数字,“[ -n "$y" ] && echo "Error! Please input a number!" && exit 18”这句脚本会执行,exit一旦执行脚本就会终止。执行下这个脚本:
2)break语句
再来看看特殊流程控制语句break的作用,当程序执行到break语句时,会结束整个当前循环。而continue语句也是结束循环的语句,不过continue语句单次当前循环,而下次循环会继续。有点晕菜吧,画个示意图解释下break语句,如图所示:
举个例子:
执行下这个脚本,因为一旦变量i的值等于4,整个循环都会跳出,所以应该只能循环三次:
3)continue语句
再来看看continue语句,continue也是结束流程控制的语句。如果在循环中,continue语句只会结束单次当前循环,也画个示意图来说明下continue语句,如图所示:
还是用刚刚的脚本,不过退出语句换成continue语句,看看会发生什么情况:
运行下这个脚本:
ontinue只会退出单次循环,所以并不影响后续的循环,所以只会少4的输出。这个例子和break的例子做个比较,应该可以更清楚的说明break和continue的区别。
-
-
END
END也是awk保留字,不过刚好和BEGIN相反。END是在awk程序处理完所有数据,即将结束时执行。END后的动作只在程序结束时执行一次。例如:
-
-
关系运算符
举几个例子看看关系运算符。假设我想看看平均成绩大于等于87分的学员是谁,就可以这样输入命令:
-
这里要注意在awk中,使用“//”包含的字符串,awk命令才会查找。也就是说字符串必须用“//”包含,awk命令才能正确识别。
-
正则表达式
如果要想让awk识别字符串,必须使用“//”包含,例如:
-
-
字符串替换
“c”动作是进行整行替换的,如果仅仅想替换行中的部分数据,就要使用“s”动作了。s动作的格式是: