awk基本语法介绍及操作
- awk是一种处理文本文件的编程语言,文件的每行数据被称为记录,默认以空格或制表符为分隔符,每条记录会被分成若干字段(列),awk每次从文件中读取一条记录。
语法格式
awk [选项] '条件{动作} 条件{动作} ... ...' 文件名 ...
内置变量
变量名 | 功能描述 |
---|---|
FILENAME | 当前输入文档的名称 |
FNR | 当前输入文档的当前行号,尤其当有多个输入文档时有用 |
NR | 输入数据流的当前行号 |
$0 | 当前的全部数据内容 |
$n… | 当前行的第n个字段的内容 |
NF | 当前记录行的字段列个数 |
FS | 字段分隔符,默认空格或TAB |
OFS | 输出字段分隔符,默认为空格 |
ORS | 输出记录分隔符,默认为\n |
RS | 输入记录分隔符,默认为\n |
free
free | awk '{print $2}' #逐行打印第二列
free | awk '{print NR}' #输出行号
free | awk '{print NR}' #输出每行数据的列数
vim test1.txt
hello the world!
My name is Cauchy, I can fly.
Seen is believing.
vim test2.txt
root:www:httpd
openstack::nova,api
fruit:apple,banana--peach:eat
awk '{print $0}' test1.txt #打印全部内容
awk '{print}' test1.txt #同上
#打印两个文件的行号
awk '{print NR}' test1.txt test2.txt
awk '{print FNR}' test1.txt test2.txt
- NR与FNR的区别:NR会将所有文件的数据视为一个数据流,NR仅保存这些数据流递增的行号,而FNR是将多个文件的数据视为独立的若干个数据流,遇到新文件时行号会从1开始重新递增。
awk '{print NF}' test1.txt #打印每行数据列数
awk '{print $NF}' test1.txt #打印最后一列
awk '{print $(NF-1)}' test1.txt #打印倒数第二列
awk '{print $(NF-2)}' test1.txt #打印倒数第三列
awk '{print FILENAME}' test1.txt #打印文件名
- 为什么会输出三次文件名呢?
- 答:awk是逐行处理软件,满足要求则执行动作指令
自定义变量
- awk可以通过-v选项来设置或者修改变量的值。
awk -v x="Cauchy" '{print x}' test1.txt #定义变量,输出变量值
awk -v x="Cauchy" -v y=25 '{print x,y}' test1.txt
awk -v x="Cauchy" -v y=25 '{print y,x}' test1.txt
x="dd" #自定义系统变量
awk -v i=$x '{print i}' test1.txt #awk调用
y="jj"
awk '{print "'$y'"}' test1.txt #awk调用
awk -v FS=":" '{print $1}' test2.txt #重新定义分隔符号为“:”
awk -v FS=":" '{print $2}' test2.txt
- 我们还可以用[]定义分隔符集合,如果有-分隔符千万不能放到中间,放到中间表示的是范围
awk -v FS="[:,-]" '{print $1}' test2.txt
awk -v FS="[:,-]" '{print $2}' test2.txt
awk -v FS="[:,-]" '{print $3}' test2.txt
awk -v FS="[:,-]" '{print $4}' test2.txt
- -F可以直接指定数据字段的分隔符
awk -F"[:,-]" '{print $1}' test2.txt
awk -F: '{print $1}' test2.txt
- RS保存的是输入数据的记录分隔符,默认值为\n换行符。
awk -v RS="," '{print $1}' test1.txt
-
使用","作为分隔符符代替了\n换行符,则第一行数据为:hello the world!\nMy name is Cauchy。第二行数据为:I can fly.\nSeen is believing.。
-
OFS保存的是输出字段的分隔符,默认为空格;而ORS保存的是输出记录的分隔符,默认为\n换行符。
awk -v OFS=":" '{print $1 $2 $3}' test1.txt #定义字段分隔符为冒号
awk -v OFS="-" '{print $1 $2 $3}' test1.txt #定义字段分隔符为减号
awk -v OFS="\t" '{print $1 $2 $3}' test1.txt #定义字段分隔符为制表符
awk -v OFS=". " '{print NR,$1}' test1.txt #定义字段分隔符为点号和空格,并且打印出行号和$1内容
awk -v ORS="-" '{print}' test1.txt #定义行分隔符为减号,并打印全部内容
print指令
- print输出特定数据时,我们可以输出变量数据,同时还能直接输出常量,字符串常量需要用双引号。
awk '{print "ABCD"}' test1.txt
awk '{print "ABCD",$1}' test1.txt
awk '{print 1234}' test1.txt
awk '{print $1,1234,$3}' test1.txt
awk '{print "第一列:"$1,"\t第二列:"$2}' test1.txt
条件匹配
- awk支持正则进行模糊匹配,也支持字符串和数字精确匹配,并支持逻辑与,或。
比较符号 | 功能描述 |
---|---|
// | 全行数据正则匹配 |
//! | 全行数据正则匹配后取反 |
~// | 对特定数据正则匹配 |
!~// | 对特定数据正则匹配后取反 |
== | 等于 |
!= | 不等于 |
> | 大于 |
>= | 大于等于 |
< | 小于 |
<= | 小于等于 |
&& | 逻辑与 |
ll | 逻辑或 |
awk '/hello/{print}' test1.txt #打印包含hello的行
awk '/hello/' test1.txt #打印包含hello的行
awk '/name/' test1.txt #每行正则包含name
awk '$2~/the/' test1.txt #每行第二列正则匹配the
awk '$2~/name/{print $1,$3,$5}' test1.txt #每行第二列正则匹配the,并打印其1,3,5列
vim test3.txt
I like reading book
I will go to the hospital
I wont work too much homework
awk '$4~/to/' test3.txt #正则匹配第四列包含to的行
awk '$4=="to"' test3.txt #精确匹配
awk '$2!="like"' test3.txt #第二列不等于like
awk -F: '$3<=10' /etc/passwd #匹配第三列小于等于10的行
awk -F: '$3>=100' /etc/passwd #匹配第三列大于等于100的行
awk -F: '$3<=10{print $1}' /etc/passwd #匹配第三列小于等于10的行,并打印第一列
awk 'NR==4' /etc/passwd #仅显示第四行数据元素
awk -F: '$3>1&&$3<5' /etc/passwd #逻辑与
awk -F: '$3==1||$3==5' /etc/passwd #逻辑或
- awk的匹配条件是BEGIN和END,BEGIN会导致动作指令仅在读取任何数据记录之前执行一次,END会导致动作指令仅在读取完所有的数据记录之后执行一次,BEGIN初始化操作,END数据汇总操作。
awk 'BEGIN{print "OK"}'
awk 'BEGIN{print "OK"}' /etc/passwd
awk 'END{print NR}' /etc/passwd
awk -F: 'BEGIN{print "用户名\tUID\t解释器"} \
{print $1"\t",$3"\t",$7} \
END{print "总计有"NR"个账户."}' /etc/passwd
- awk的算术运算
awk 'BEGIN{print 1+1}'
awk 'BEGIN{print 1-1}'
awk 'BEGIN{print 1*1}'
awk 'BEGIN{print 3/8}'
awk 'BEGIN{print 3%8}'
awk 'BEGIN{print 2**8}'
awk 'BEGIN{x=6;y=3;print x+y}'
awk 'BEGIN{x=6;y=3;print x-y}'
awk 'BEGIN{x=6;y=3;print x*y}'
awk 'BEGIN{x=6;y=3;print x/y}'
awk 'BEGIN{x=6;y=3;print x%y}'
awk 'BEGIN{x=1;x++;print x}'
awk 'BEGIN{x=1;x--;print x}'
awk 'BEGIN{x=2;x*=2;print x}'
awk 'BEGIN{x=2;x/=2;print x}'
awk 'BEGIN{x=2;x%=2;print x}'
- 未定义变量默认值为0,字符串为空
- awk统计用法
awk '/bash$/{x++} END{print x}' /etc/passwd
who | awk '/root/{x++} END{print x}'
seq 200 |awk '$1%7==0 && $1~/7/' #统计200以内被7整除且数字中带有7的元素
df |tail -n +2 |awk '{sum+=$4} END{print sum}' #统计磁盘总量
ls -l /etc/*.conf |awk '{sum+=$5} END{print sum}' #统计conf配置文件总量
ls -l /etc/ |awk '/^-/{sum+=$5} END{print "文件总量为:"sum"."}' #统计普通文件总量(普通文件为-)