一、awk概述
grep、sed与awk,俗称Linux下的三剑客,它们之间有很多相似点,但是同样也各有各的特色。
相似的地方:它们都可以匹配文本,逐行读取数据,支持正则表达式
其中只有sed可以编辑源文件
而awk则是一门模式匹配的编程语言,因为它的主要功能是用于匹配文本并格式化输出,同时它有一些编程语言才有的语法,例如函数、分支循环语句、变量等等
awk:报告生成器,格式化打印
基于列的文本工具,按行读取文本并视为一条记录,每条记录以指定分割符分割成若干字段,然后输出各字段的值。
内部支持变量、条件判断、循环、数组
awk --> new awk --> nawk(收费)
GNU awk --> gawk
二、awk的使用
注意:
awk和默认以任意个空白符为分隔符,而cut默认以制表符为分隔符,而且只能指定以一个字符为分隔符。
与sed一样使用‘’不要使用""容易报错
awk只支持ERE,且默认不支持{m,n}加选项 -- posix或者-- re-interval才支持,不支持反向引用:\1,\2,、、、,&等
用法格式:
awk [OPTIONS] 'SCRIPT' FILE...
awk [OPTIONS] 'pattern/{action}' File...
1、OPTIONS:
-F:指定输入文本时所使用的字段分隔符
-v:自定义变量
2、pattern
包括地址定界:
/pat1/,/pat2/
/pattern/
!/pattern/
expression: 表达式如:>,<,=,>=,<=,=,!=,==,~
3、BEGIN语句
在awk开始从输入流中读取行之前被执行,这是一个可选的语句块,比如变量初始化、打印输出表格的表头等语句通常可以写在BEGIN语句块中。
4、END语句
在awk从输入流中读取完所有的行之后即被执行,比如打印所有行的分析结果这类信息汇总都是在END语句块中完成,它也是一个可选语句块。
[root@xxj shell]# awk -F : '/^root/ {print $1}' /etc/passwd root [root@xxj shell]# awk -F: '/^\<root\>/ {print $1}' /etc/passwd root [root@xxj shell]# awk -F : '/^root/ {print $1,$7}' /etc/passwd #逗号只是命令的一部分,不是输出的结果 root /bin/bash #使用表达式做定界 [root@Note3 src]# awk -F: '$7='/bin/bash/' {print$1}' /etc/passwd awk: $7=/bin/bash/ {print$1} awk: ^ syntax error [root@Note3 src]# awk -F: '$3 > 500' /etc/passwd #不指定输出的字段,则默认输出所有字段 baiyu:x:501:2016::/home/anyfish:/bin/bash slackware:x:2002:2017::/home/slackware:/bin/tcsh [root@Note3 src]# awk -F: '$3 > 500 {print $1,$3}' /etc/passwd baiyu 501 slackware 2002 [root@Note3 src]# awk -F: '$7="/bin/bash/" {print$1}' /etc/passwd root bin daemon adm lp sync [root@Note3 src]# awk -F: '$7 ~ bash {print $1}' /etc/passwd root bin daemon adm lp sync
BEGIN,END:
[root@xxj shell]# awk -F: '$3>=500 {print "-------------\n"$1}' /etc/passwd ------------- testbash ------------- basher ------------- nologin ------------- fedora ------------- user1 ------------- bash1 ------------- xj ------------- Oracle ------------- bash ------------- xxj ------------- openstack ------------- centos [root@xxj shell]# awk -F: '$3>=500 {print $1}END{print "-------"}' /etc/passwd testbash basher nologin fedora user1 bash1 xj Oracle bash xxj openstack centos ------- [root@xxj shell]# awk 'BEGIN{FS=":"} $3>=500 {print $7} ' /etc/passwd /bin/bash #用BEGIN指定分隔符 /bin/bash /sbin/nologin /bin/bash /bin/bash /bin/bash /bin/bash /bin/bash /bin/bash /bin/bash /bin/bash /bin/bash #BEGIN语句中使用;分隔多个语句 [root@xxj shell]# awk -F: 'BEGIN{print "Username\n----------"}$3>=500 {print $1}' /etc/passwd Username ---------- testbash basher nologin fedora user1 bash1 xj Oracle bash xxj openstack centos [root@Note3 ~]# awk 'BEGIN{FS=":";OFS=":"}{print $1,$7}' /etc/passwd root:/bin/bash bin:/sbin/nologin daemon:/sbin/nologin adm:/sbin/nologin lp:/sbin/nologin sync:/bin/sync shutdown:/sbin/shutdown halt:/sbin/halt mail:/sbin/nologin
练习1:
1、显示GID小于500的组的组名
# awk -F: '$3<500{print $1}'
2、显示默认shell为nologin的用户
# awk -F: '/\<nologin$/ {print $1}'
# awk -F: '$7=="/sbin/nologin" {print $1}'
3、显示eh0网卡文件的配置信息,注意只显示=后面的值
# awk -F= '{print $2}'
4、显示/etc/sysctl.conf文件中定义的内核参数,只显示名称
# awk -F= '/^[^#]/ {print $1}'
5、显示eth0网卡的ip地址,通过Ifconfig的命令结果进行过滤
# ifconfig eth0|awk -F: '/inet addr/{print $2}'|awk '{print $1}'
5、awk的内置变量
$1,$2,$3...:第1个字段,第2个字段,第3个字段...
$0:表示整行
$NF:表示最后一个字段
NF:Number of Field,当前记录的field(字段)个数;
FS: field separator 输入文件本时,所使用字段分隔符;默认空格
RS:Record separator 输入文本信息所使用的换行符;默认是换行符
OFS: Output Filed Separator 输出文本时所使用字段分隔符,默认空格,
但在语句中要使用逗号(print的使用方法)
ORS:Output Row Separator 输出文本时所使用行分隔符,默认换行符
NR: The number of input records,awk命令所处理的行记录数;如果有多个文件,这个数目会把处理的多个文件中行统一计数;(多各文件一起计数)
FNR: 与NR不同的是,FNR用于记录正处理的行是当前这一文件中的行数;(多各文件不一起计数)
ARGV: 数组,保存命令行本身这个字符串,如awk '{print $0}' a.txt b.txt这个命令中,
ARGV[0]保存awk,ARGV[1]保存a.txt;ARGV[2]保存b.txt
ARGC: awk命令的参数的个数;
FILENAME: awk命令所处理的文件的名称;在命令中获取当前文件名
ENVIRON:当前shell环境变量及其值的关联数组;
在awk中引用变量不要加$
[root@Node4 src]# awk 'BEGIN{print 1+1}' 2 [root@Node4 src]# awk 'BEGIN{print 1*1}' 1 [root@Node4 src]# awk 'BEGIN{print 1.01**365}' 37.7834 [root@Node4 src]# awk BEGIN'{print 1.01**365}' 37.7834 [root@Node4 src]# cat /etc/issue CentOS release 6.5 (Final) Kernel \r on an \m [root@Node4 src]# awk '{print NR,NF}' /etc/issue 1 4 2 5 3 0 [root@Node4 src]# awk '{print $NR,$NF}' /etc/issue CentOS (Final) \r \m [root@Node4 src]# awk '{print NR,$NF}' /etc/issue /etc/issue 1 (Final) 2 \m 3 4 (Final) 5 \m 6 [root@Node4 src]# awk '{print FNR,$NF}' /etc/issue /etc/issue 1 (Final) 2 \m 3 1 (Final) 2 \m 3 # ARGV与ARGC [root@Node4 src]# awk '{print ARGV[0]}' /etc/issue awk awk awk [root@Node4 src]# awk '{print ARGC}' /etc/issue # 把{print ARGC}也当作一个参数 2 2 2
6、用户自定义变量
1)在命令行中使用赋值变量
在“脚本”外为变量赋值,并在脚本中进行引用。例如,上述的例子还可以改写为:
awk -v var1="str1" -v var2="str2" 'BEGIN{print var1,var2}'
2)在脚本中赋值变量
在awk中给变量赋值使用赋值语句进行,例如:
awk 'BEGIN{var="variable testing";print var}'
3)将外部变量传递给awk
[root@localhost ~]# awk -v var1=aaa -v var2=bbb 'BEGIN{print var1,var2}' aaa bbb [root@localhost ~]# awk -v var1=aaa -v var2=bbb 'BEGIN{print var1 var2}' aaabbb [root@localhost ~]# awk 'BEGIN{var1="aaa";var2="bbb";print var1,var2}' aaa bbb [root@localhost ~]# var1=aaa [root@localhost ~]# echo|awk -v x=$var1 '{print x}' aaa [root@localhost ~]# var=aaa [root@localhost ~]# echo|awk '{print x}' x=$var aaa
7、action
print,默认打印,不能在bash中单独使用
printf,用于能够实现格式化输出的工具,
1)print的使用格式:
print item1, item2, ...
各项目之间使用逗号隔开,而输出时则以空白字符分隔;
输出的item可以为字符串或数值、当前记录的字段(如$1)、变量或awk的表达式;数值会先转换为字符串,而后再输出;
print命令后面的item可以省略,此时其功能相当于print $0, 因此,如果想输出空白行,则需要使用print "";
printf命令的使用格式:
printf "format", item1, item2, ...
要点:
其与print命令的最大不同是,printf需要指定format;
format用于指定后面的每个item的输出格式;
printf语句不会自动打印换行符;\n
format格式的指示符都以%开头,后跟一个字符;如下:
%c: 显示字符的ASCII码;
%d, %i:十进制整数;
%e, %E:科学计数法显示数值;
%f: 显示浮点数;
%g,%G: 以科学计数法的格式或浮点数的格式显示数值;
%s: 显示字符串;
%u: 无符号整数;
%%: 显示%自身;
修饰符:
N: 显示宽度(占多少各字符);
-: 左对齐;
+:显示数值符号;
[root@localhost ~]# awk -F: '/root/{print $1,$3}' /etc/passwd root 0 operator 11 [root@localhost ~]# awk -F: '/root/{print $1$3}' /etc/passwd root0 operator11 [root@localhost ~]# awk -F: '/root/{print $1 $3}' /etc/passwd root0 operator11 [root@localhost ~]# awk -F: '/root/{print}' /etc/passwd root:x:0:0:root:/root:/bin/bash operator:x:11:0:operator:/root:/sbin/nologin [root@localhost ~]# awk -F: '/root/{print ''}' /etc/passwd root:x:0:0:root:/root:/bin/bash operator:x:11:0:operator:/root:/sbin/nologin [root@localhost ~]# awk -F: '/root/{print ""}' /etc/passwd [root@localhost ~]# [root@localhost ~]# awk -F: '/root/{printf $1,$3}' /etc/passwd rootoperator[root@localhost ~]# [root@localhost ~]# awk -F: '/root/{printf "%s%s\n",$1,$3}' /etc/passwd root0 operator11 [root@localhost ~]# awk -F: '/root/{printf "%s %s\n",$1,$3}' /etc/passwd root 0 operator 11 [root@localhost ~]# awk -F: '/root/{printf "%s,%s\n",$1,$3}' /etc/passwd root,0 operator,11 [root@localhost ~]# awk -F: '/root/{printf "%s:%s\n",$1,$3}' /etc/passwd root:0 operator:11 [root@localhost ~]# awk -F: '/root/{printf "%10s:%s\n",$1,$3}' /etc/passwd root:0 operator:11 [root@localhost ~]# awk -F: '/root/{printf "%-10s:%s\n",$1,$3}' /etc/passwd root :0 operator :11
输出重定向
print items > output-file
print items >> output-file
print items | command
特殊文件描述符:
/dev/stdin:标准输入
/dev/sdtout: 标准输出
/dev/stderr: 错误输出
/dev/fd/N: 某特定文件描述符,如/dev/stdin就相当于/dev/fd/0;
[root@localhost ~]# awk -F: '/root/{printf "%-10s:%s\n",$1,$3}' /etc/passwd > /dev/null [root@localhost ~]# awk -F: '/root/{printf "%-10s",$1 > /dev/null}' /etc/passw
8、awk的操作符
算术操作符:
-x: 负值
+x: 转换为数值;
x^y:
x**y: 次方
x*y: 乘法
x/y:除法
x+y:
x-y:
x%y:
字符串操作符:
只有一个,而且不用写出来,用于实现字符串连接;(空格)
赋值操作符:
=
+=
-=
*=
/=
%=
^=
**=
++
--
注意:如果模式自身是=号,此时使用/=/可能会有语法错误,应以/[=]/替代
比较操作符:
<
<=
>
>=
==
!=
~:模式匹配,左边的字符串能够被右边的模式所匹配为真,否则为假;
!~:
逻辑操作符
&&:与
||:或
布尔值
awk中,任何非0值或非空字符串都为真,反之就为假;(和bash的命令执行状态返回值刚好相反)