awk命令
grep:更适合单纯的查找或匹配文本
sed:更适合编辑文本
awk:更适合格式化文本,对文本进行较复杂格式处理。
awk
awk是行处理器: 相比较屏幕处理的优点,在处理庞大文件时不会出现内存溢出或是处理缓慢的问题,通常用来格式化文本信息
awk处理过程:依次对每一行进行处理,然后输出
awk命令形式:awk [-F|-f|-v] ‘BEGIN{} //{command1; command2} END{}’ file
[-F|-f|-v] 大参数,-F指定分隔符,-f调用脚本,-v定义变量 var=value
' ' 引用代码块
BEGIN 初始化代码块,在对每一行进行处理之前,初始化代码,主要是引用全局变量,设置FS分隔符
// 匹配代码块,可以是字符串或正则表达式
{} 命令代码块,包含一条或多条命令
; 多条命令使用分号分隔
END 结尾代码块,在对每一行进行处理之后再执行的代码块,主要是进行最终计算或输出结尾摘要信息
特殊要点:
$0 表示整个当前行
$1 每行第一个字段
NF 字段数量变量
NR 每行的记录号,多文件记录递增
FNR 与NR类似,不过多文件记录不递增,每个文件都从1开始
\t 制表符
\n 换行符
FS BEGIN时定义分隔符
RS 输入的记录分隔符, 默认为换行符(即文本是按一行一行输入)
~ 匹配,与==相比不是精确比较
!~ 不匹配,不精确比较
== 等于,必须全部相等,精确比较
!= 不等于,精确比较
&& 逻辑与
|| 逻辑或
+ 匹配时表示1个或1个以上
/[0-9][0-9]+/ 两个或两个以上数字
/[0-9][0-9]*/ 一个或一个以上数字
FILENAME 文件名
OFS 输出字段分隔符, 默认也是空格,可以改为制表符等
ORS 输出的记录分隔符,默认为换行符,即处理结果也是一行一行输出到屏幕
-F'[:#/]' 定义三个分隔符
print & $0
print 是awk打印指定内容的主要命令
awk '{print}' /etc/passwd == awk '{print $0}' /etc/passwd
awk '{print " "}' /etc/passwd //不输出passwd的内容,而是输出相同个数的空行,进一步解释了awk是一行一行处理文本
awk '{print "a"}' /etc/passwd //输出相同个数的a行,一行只有一个a字母
awk -F":" '{print $1}' /etc/passwd
awk -F: '{print $1; print $2}' /etc/passwd //将每一行的前二个字段,分行输出,进一步理解一行一行处理文本
awk -F: '{print $1,$3,$6}' OFS="\t" /etc/passwd //输出字段1,3,6,以制表符作为分隔符
-f指定脚本文件
awk -f script.awk file
BEGIN{
FS=":"
}
{print $1} //效果与awk -F":" '{print $1}'相同,只是分隔符使用FS在代码自身中指定
awk 'BEGIN{X=0} /^$/{ X+=1 } END{print "I find",X,"blank lines."}' test
I find 4 blank lines.
ls -l|awk 'BEGIN{sum=0} !/^d/{sum+=$5} END{print "total size is",sum}' //计算文件大小
total size is 17487
-F指定分隔符
$1 指指定分隔符后,第一个字段,$3第三个字段, \t是制表符
一个或多个连续的空格或制表符看做一个定界符,即多个空格看做一个空格
awk -F":" '{print $1}' /etc/passwd
awk -F":" '{print $1 $3}' /etc/passwd //$1与$3相连输出,不分隔
awk -F":" '{print $1,$3}' /etc/passwd //多了一个逗号,$1与$3使用空格分隔
awk -F":" '{print $1 " " $3}' /etc/passwd //$1与$3之间手动添加空格分隔
awk -F":" '{print "Username:" $1 "\t\t Uid:" $3 }' /etc/passwd //自定义输出
awk -F: '{print NF}' /etc/passwd //显示每行有多少字段
awk -F: '{print $NF}' /etc/passwd //将每行第NF个字段的值打印出来
awk -F: 'NF==4 {print }' /etc/passwd //显示只有4个字段的行
awk -F: 'NF>2{print $0}' /etc/passwd //显示每行字段数量大于2的行
awk '{print NR,$0}' /etc/passwd //输出每行的行号
awk -F: '{print NR,NF,$NF,"\t",$0}' /etc/passwd //依次打印行号,字段数,最后字段值,制表符,每行内容
awk -F: 'NR==5{print}' /etc/passwd //显示第5行
awk -F: 'NR==5 || NR==6{print}' /etc/passwd //显示第5行和第6行
route -n|awk 'NR!=1{print}' //不显示第一行
awk '{print $1,$2,$3}' Nym.RPKM.20160923.txt:打印出Nym文件的第1,2,3 列
awk '{print $1 "\t" $2 "\t" $3}' Nym.RPKM.20160923.txt:打印出整齐的三列,中间去掉逗号,需要加带双引号的制表符"\t"
条件表达式
== != > >=
awk -F":" '$1=="mysql"{print $3}' /etc/passwd
awk -F":" '{if($1=="mysql") print $3}' /etc/passwd //与上面相同
awk -F":" '$1!="mysql"{print $3}' /etc/passwd //不等于
awk -F":" '$3>1000{print $3}' /etc/passwd //大于
awk -F":" '$3>=100{print $3}' /etc/passwd //大于等于
awk -F":" '$3<1{print $3}' /etc/passwd //小于
awk -F":" '$3<=1{print $3}' /etc/passwd //小于等于
逻辑运算符
&& 逻辑与
|| 逻辑或
awk -F: '$1~/mail/ && $3>8 {print }' /etc/passwd //逻辑与,$1匹配mail,并且$3>8
awk -F: '{if($1~/mail/ && $3>8) print }' /etc/passwd
awk -F: '$1~/mail/ || $3>1000 {print }' /etc/passwd //逻辑或
awk -F: '{if($1~/mail/ || $3>1000) print }' /etc/passwd
数值运算
awk -F: '$3 > 100' /etc/passwd
awk -F: '$3 > 100 || $3 < 5' /etc/passwd
awk -F: '$3+$4 > 200' /etc/passwd
awk -F: '/mysql|mail/{print $3+10}' /etc/passwd //第三个字段加10打印
awk -F: '/mysql/{print $3-$4}' /etc/passwd //减法
awk -F: '/mysql/{print $3*$4}' /etc/passwd //求乘积
awk '/MemFree/{print $2/1024}' /proc/meminfo //除法
awk '/MemFree/{print int($2/1024)}' /proc/meminfo //取整
输出分隔符OFS
awk '$6 ~ /FIN/ || NR==1 {print NR,$4,$5,$6}' OFS="\t" netstat.txt
awk '$6 ~ /WAIT/ || NR==1 {print NR,$4,$5,$6}' OFS="\t" netstat.txt
//输出字段6匹配WAIT的行,其中输出每行行号,字段4,5,6,并使用制表符分割字段
输出处理结果到文件
①在命令代码块中直接输出 route -n|awk 'NR!=1{print > "./fs"}'
②使用重定向进行输出 route -n|awk 'NR!=1{print}' > ./fs
示例演示:
指定输出行或列
在awk中一行叫record,一列叫field。用NR和NF即可指定输出行或列。
NR:number of record 表示打印出行的数量
NF:number of field 表示打印出列的数量
1、输出第4行:awk 'NR==4{print NR,$0}' Nym.RPKM.20160923.txt
'NR==4{print NR,$0}'
2、输出第4列:awk '{print NF,$4}' Nym.RPKM.20160923.txt,去掉NF则不显示左边总列数。
awk '{print NF,$4}'
3、输出第4行第4列:
awk 'NR==4{print $4}' Nym.RPKM.20160923.txt,显示一个数字。
4、输出第4-8列,一步命令(暂时还没学会,后面更新):
awk 'NR==1{print $0}' Nym.RPKM.20160923.txt:先查看所有的列名,数。
awk '{print NR,$4,$5,$6,$7,$8}' OFS="\t" Nym.RPKM.20160923.txt,加OFS="\t"可使列显示很整齐。
'{print NR,$4,$5,$6,$7,$8}' OFS="\t"
5、输出第4列大于1的数并显示行号:
awk '$4>1{print NR,$1,$4}' OFS="\t" Nym.RPKM.20160923.tx
'$4>1{print NR,$1,$4}' OFS="\t"
6、输出第4列大于等于0.5小于1的行,并显示行号:
awk '$4>=0.5 && $4<=1{print NR, $1,$4}' OFS="\t" Nym.RPKM.20160923.txt,逻辑与
'$4>=0.5 && $4<=1{print NR, $1,$4}'
7、输出第4列小于等于0.5或大于等于1的行,并显示行号:
awk '$4<=0.5 || $4>=1{print NR, $1,$4}' OFS="\t" Nym.RPKM.20160923.txt,逻辑或
'$4<=0.5 || $4>=1{print NR, $1,$4}'
8、输出第3列大于1且第4列小于1的行,并显示行号:
awk '$3>1 && $4<1{print NR, $1,$3,$4}' OFS="\t" Nym.RPKM.20160923.txt,逻辑与
'$3>1 && $4<1{print NR, $1,$3,$4}'
9、输出第3列和第4列等于0的行:
awk '$3==0 && $4==0{print NR, $1,$3,$4}' OFS="\t" Nym.RPKM.20160923.txt,指定一个数,必须要用双等号==赋值
'$3==0 && $4==0{print NR, $1,$3,$4}'
10、打印出带有行号的第1到3列:awk '{print NR, $1 "\t" $2 "\t" $3}' Nym.RPKM.20160923.txt
NR,
11、打印出所有列数,显示在左边:awk '{print NF $0}' Nym.RPKM.20160923.txt
NF,
$0表示打印出所有,如果要空一格,用逗号隔开或用"\t":awk '{print NF, $0}' Nym.RPKM.20160923.txt或awk '{print NF "\t" $0}' Nym.RPKM.20160923.txt。(awk中的空格是认为要把左边和右边字符串拼接起来)。
12、打印出第一列字符串为Nym的所有列:awk '$1==“Nym.canu0775170”{print NR, $0}' Nym.RPKM.20160923.txt,字符串加双引号“”,否则会默认为数值型不显示出来。
'$1==“Nym.canu0775170”{print NR, $0}'
13、显示部分:awk '$1==“Nym.canu0775170”{print NR, $1,$3}' Nym.RPKM.20160923.txt
'$1==“Nym.canu0775170”{print NR, $1,$3}'
14、筛选有8列的行:awk 'NF==8{print NR,$0}' Nym.RPKM.20160923.txt
'NF==8{print NR,$0}'
15、输入分隔符:awk ‘BEGIN{FS=“,”}{print $1,$2}’
输出分隔符:awk ‘BEGIN{OFS=“,”}{print $1,$2}’
合并:awk ‘BEGIN{FS=“,”;OFS=“ \t ”}{print $1,$2}’,输出后会出现制表符。
awk
16、同时读取两个文件内容:awk ‘{print NR, FILENAME,$0}’ file1.txt file2.txt
展示出每一行有多少列:awk {print NF} file1.txt
筛选出每一行的最后一列:awk ‘{print $NF}’ file1.txt
筛选出每一行的倒数第二列:awk ‘{print $(NF-1)}’ file1.txt
awk计算
正则表达式// 结合awk
(1)筛选出含abc的内容:awk ‘/abc/{print $0}’ file1.txt ,直接指定并匹配
(2)筛选出含a和c的内容:awk ‘/a.c/{print $0}’ file1.txt 点表示匹配任意一个字母
(3)筛选出含a.c的内容:awk ‘/a\.c/{print $0}’ file1.txt 需要加一个转译字符\ 右斜杠
(4)筛选出含a/c的内容:
awk ‘/a\/c/{print $0}’ file1.txt 转译字符‘/a\/c/
a\c : awk ‘/a\\c/{print $0}’ file1.txt
a?c : awk ‘/a\?c/{print $0}’ file1.txt
(5)^开始 $结尾
/^abc/:匹配所有开头为abc 的字符
/abc$/:匹配所有结尾为abc 的字符 ,如awk ‘/abc$/’{print $0} file1.txt
/a[xyz]c/
/a[a-z]c/
/a[a-zA-Z]c/
(6)* +
/a*b/ :*跟在一个字母后面表示这个字母可以在匹配结果中出现0次或多次
/a+b/:+表这个字母至少要出现1次
(7)?
/a?b/:?表a可以有可以没有
(8){}
/ab{3}c/ :表b必须出现3次
/ab{3,4}c/ :表b可以出现3-4次
/ab{3,}c/ :表b的次数不限,但不能出现其他字母
(9)():把一串东西看成一个整体
/(ab)+c/ :把ab看成一个整体,同时出现,次数不限,最后c结尾