awk基础
awk介绍,awk基本语法,直接使用action,打印列,初识列和行,\$0、\$NF、NF,基础示例,begin模式,end模式
awk介绍
awk其实是一门编程语言,它支持条件判断、数组、循环等功能。所以可以把awk理解成一个脚本语言解释器。
grep 、sed、awk被称为linux中的"三剑客"。
他们的特点:
grep 更适合单纯的查找或匹配文本
sed 更适合编辑匹配到的文本
awk 更适合格式化文本,对文本进行较复杂格式处理
awk基本语法
基本语法
awk [options] 'program' file1 , file2 , ```
对于上述语法中的program来说,又可以细分成pattern和action,也就是说,awk的基本语法如下
awk [options] 'Pattern{Action}' file
action指的就是动作,awk擅长文本格式化,并且将格式化以后的文本输出,所以awk最常用的动作就是print和printf.
直接使用action
先从最简单用法开始了解awk,先不使用[options] ,也不指定pattern,直接使用最简单的action,从而开始认识awk。
[root@node1 course]# echo zaishu>awktest
[root@node1 course]# awk '{print}' awktest
zaishu
打印列
[root@node1 course]# df -h
Filesystem Size Used Avail Use% Mounted on
/dev/mapper/centos-root 48G 4.6G 44G 10% /
devtmpfs 223M 0 223M 0% /dev
tmpfs 235M 0 235M 0% /dev/shm
tmpfs 235M 5.5M 229M 3% /run
tmpfs 235M 0 235M 0% /sys/fs/cgroup
/dev/sda1 197M 125M 73M 64% /boot
tmpfs 47M 0 47M 0% /run/user/0
[root@node1 course]# df -h | awk '{print $4}'
Avail
44G
223M
235M
229M
235M
73M
47M
上图中的awk ‘{print $4}’,表示输出df的信息的第4列,$4表示将当前行按照分隔符分割后的第4列,不指定分隔符时,默认使用空格作为分隔符,细心的你一定发现了,上述信息用的空格不止有一个,而是有连续多个空格,awk自动将连续的空格理解为一个分割符了。
初识列和行
awk是逐行处理的,逐行处理的意思就是说,当awk处理一个文本时,会一行一行进行处理,处理完当前行,再处理下一行,awk默认以"换行符"为标记,识别每一行,也就是说,awk跟我们人类一样,每次遇到"回车换行",就认为是当前行的结束,新的一行的开始,awk会按照用户指定的分割符去分割当前行,如果没有指定分割符,默认使用空格作为分隔符。
$0、$NF、NF
$0和$NF均为内置变量;$0 表示显示整行;$NF表示当前行分割后的最后一列
注意,$NF 和 NF 要表达的意思是不一样的,对于awk来说,$NF表示最后一个字段,NF表示当前行被分隔符切开以后,一共有几个字段。
awk自动将连续的空格理解为一个分割符了,如果没有指定分割符,默认使用空格作为分隔符。
假如一行文本被空格分成了7段,那么NF的值就是7,$NF的值就是$7, 而$7表示当前行的第7个字段,也就是最后一列,那么每行的倒数第二列可以写为$(NF-1)。
基础示例
[root@node1 course]# cat awktxt
zaishu mysql qq
xasdf xxx sdfsadf
dd xx
sadf sdfsad
sadfdsaf sadfsadf sdfsa dfd
可以一次输出多个列
打印多列
[root@node1 course]# awk '{print $2,$3,$4}' awktxt
mysql qq
xxx sdfsadf
xx
sdfsad
sadfsadf sdfsa dfd
多行没有对应的列,所以并没有输出任何文本,而第五行有第所有列,所以输出了。
添加字段作为列的内容
[root@node1 course]# awk '{print $2,$3,"test"}' awktxt
mysql qq test
xxx sdfsadf test
xx test
sdfsad test
sadfsadf sdfsa test
[root@node1 course]# awk '{print "1fr:"$1,"3th:"$3}' awktxt
1fr:zaishu 3th:qq
1fr:xasdf 3th:sdfsadf
1fr:dd 3th:
1fr:sadf 3th:
1fr:sadfdsaf 3th:sdfsa
$引用列时,不能加"",否则当成普通字符串
[root@node1 course]# awk '{print $1}' awktxt
zaishu
xasdf
dd
sadf
sadfdsaf
[root@node1 course]# awk '{print "$1"}' awktxt
$1
$1
$1
$1
$1
[root@node1 course]# awk '{print "1fi:"$1}' awktxt
1fi:zaishu
1fi:xasdf
1fi:dd
1fi:sadf
1fi:sadfdsaf
[root@node1 course]# awk '{print "1fi:$1"}' awktxt
1fi:$1
1fi:$1
1fi:$1
1fi:$1
1fi:$1
整行输出
使用$0或者不使用$
[root@node1 course]# awk '{print}' awktxt
zaishu mysql qq
xasdf xxx sdfsadf
dd xx
sadf sdfsad
sadfdsaf sadfsadf sdfsa dfd
[root@node1 course]# awk '{print $0}' awktxt
zaishu mysql qq
xasdf xxx sdfsadf
dd xx
sadf sdfsad
sadfdsaf sadfsadf sdfsa dfd
初识模式(begin end)
awk的语法如下
awk [options] 'Pattern{Action}' file
awk是逐行处理的, 刚才已经说过了最常用的Action,就是print打印。
现在认识下一Pattern,也就是模式。详解介绍模式之前(模式篇幅很长),先介绍两个容易入门理解的特殊模式BEGIN和END。
BEGIN 模式指定了处理文本之前需要执行的操作
END 模式指定了处理完所有行之后所需要执行的操作
示例
在开始处理文件中的文本之前,先执行打印动作,输出的内容为"aaa",“bbb”.
[root@node1 course]# cat awktxt
zaishu mysql qq
xasdf xxx sdfsadf
dd xx
sadf sdfsad
sadfdsaf sadfsadf sdfsa dfd
[root@node1 course]# awk 'BEGIN{print "aaa","bbb"}' awktxt
aaa bbb
没有给定任何输入来源,awk就直接输出信息了,因为,BEGIN模式表示,在处理指定的文本之前,需要先执行BEGIN模式中指定的动作,而上述示例没有给定任何输入源,但是awk还是会先执行BEGIN模式指定的"打印"动作,打印完成后,发现并没有文本可以处理,于是就只完成了"打印 aaa bbb"的操作。
这个时候,如果我们想要awk先执行BEGIN模式指定的动作,再根据执我们自定义的动作去操作文本,该怎么办呢?示例如下
[root@node1 course]# awk 'BEGIN{print "aaa","bbb"} {print $1,$2}' awktxt
aaa bbb
zaishu mysql
xasdf xxx
dd xx
sadf sdfsad
sadfdsaf sadfsadf
BEGIN模式的作用就是,在开始逐行处理文本之前,先执行BEGIN模式所指定的动作。以此类推,END模式的作用就一目了然了,举例如下。
[root@node1 course]# awk '{print $1,$2} END{print "end1","end2"}' awktxt
zaishu mysql
xasdf xxx
dd xx
sadf sdfsad
sadfdsaf sadfsadf
end1 end2
可以结合BEGIN模式和END模式一起使用。示例如下
[root@node1 course]# awk 'BEGIN{print "aaa","bbb"} {print $1,$2} END{print "end1","end2"}' awktxt
aaa bbb
zaishu mysql
xasdf xxx
dd xx
sadf sdfsad
sadfdsaf sadfsadf
end1 end2