1.内置变量
FS 输入字段分隔符,默认是空格或制表符
OFS 输出字段分隔符,默认是空格
RS 输入记录分隔符,默认是换行符\n
ORS 输出记录分隔符,默认是护身符\n
NF 统计当前记录中字段个数
NR 统计记录编号,每处理一行,编号就会+1
FNR 同上,与NR不同的是处理第二个文件时,编号会重新计数
ARGC 命令行参数数量
ARGV 命令行参数数组序列数组,下标从0开始,ARGV[0]是awk
ARGIND 当前正在处理的文件索引值。第一个文件是1,第二个是2,以此类推
ENVIRON 当前系统的环境变量
FILENAME输出当前处理的文件名
IGNORECASE忽略大小写
SUBSEP 数组中下标的分隔符,默认为"\034"
在程序开始前重新赋值FS变量,改变默认分隔符为冒号,与-F一样
[root@study ~]# awk 'BEGIN{FS=":"}{print $1,"\t",$2}' /etc/passwd |head -5
root x
bin x
daemon x
adm x
lp x
也可以用-v重置这个变量
[root@study ~]# awk -vFS=':' '{print $1,"\t",$2}' /etc/passwd |head -5
root x
bin x
daemon x
adm x
lp x
也可以字符串拼接实现分隔
[root@study ~]# awk -vFS=':' '{print $1"#"$2}' /etc/passwd |head -5
root#x
bin#x
daemon#x
adm#x
lp#x
以指定字符作为行分隔符来处理记录
[root@study ~]# echo "www.baidu.com/user/test.html" | awk 'BEGIN{RS="/"}{print $0}'
www.baidu.com
user
test.html
RS也支持正则
[root@study ~]# seq -f "str%02g" 10|sed 'n;n;a----'|awk 'BEGIN{RS="-+"}{print $1}'
str01
str04
str07
str10
替换某个字符
[root@study ~]# tail -2 /etc/services |awk 'BEGIN{RS="/";ORS="#"}{print $0}'
iqobject 48619#udp # iqobject
matahari 49000#tcp # Matahari Broker
NF是字段个数
[root@study ~]# echo a b c d e f|awk '{print NF}'
6
[root@study ~]# echo a b c d e f|awk '{print $NF}'
f
[root@study ~]# echo a b c d e f|awk '{print $(NF-1)}'
e
#排除倒数第一、二列
[root@study ~]# echo a b c d e f|awk '{$NF="";$(NF-1)="";print $0}'
a b c d
#排除第一列
[root@study ~]# echo a b c d e f|awk '{$1="";print $0}'
b c d e f
打印行数
[root@study ~]# tail -5 /etc/services |awk '{print NR,$0}'
1 com-bardac-dw 48556/tcp # com-bardac-dw
2 com-bardac-dw 48556/udp # com-bardac-dw
3 iqobject 48619/tcp # iqobject
4 iqobject 48619/udp # iqobject
5 matahari 49000/tcp # Matahari Broker
#打印总行数
[root@study ~]# tail -5 /etc/services |awk 'END{print NR}'
5
#打印第三行
[root@study ~]# tail -5 /etc/services |awk 'NR==3'
iqobject 48619/tcp # iqobject
#打印第三行第2列
[root@study ~]# tail -5 /etc/services |awk 'NR==3{print $2}'
48619/tcp
#打印前三行
[root@study ~]# tail -5 /etc/services |awk 'NR<=3{print NR,$0}'
1 com-bardac-dw 48556/tcp # com-bardac-dw
2 com-bardac-dw 48556/udp # com-bardac-dw
3 iqobject 48619/tcp # iqobject
ARGC是命令行参数数量
ARGV是将命令行参数存到数组,元素由ARGC指定,数组下标从0开始
[root@study ~]# awk 'BEGIN{print ARGC}' 1 2 3
4
[root@study ~]# awk 'BEGIN{print ARGV[0]}' 1 2 3
awk
[root@study ~]# awk 'BEGIN{print ARGV[1]}' 1 2 3
1
ARGIND是当前正在处理的文件索引值,第一个文件是1,第二个文件是2,以此类推,从而可以通过这种方式判断正在处理哪个文件。
[root@study ~]# cat a b
a
b
c
c
d
e
[root@study ~]# awk '{print ARGIND,$0}'
a
0 a
^[[A^C
[root@study ~]# awk '{print ARGIND,$0}' a b
1 a
1 b
1 c
2 c
2 d
2 e
[root@study ~]# awk 'ARGIND==1{print "a->"$0};ARGIND==2{print "b->"$0}' a b
a->a
a->b
a->c
b->c
b->d
b->e
2.
ENVIRON调用系统变量,如果是设置的环境变量,还需要用export导入到系统变量才可以调用
[root@study ~]# awk 'BEGIN{print ENVIRON["HOME"],ENVIRON["USER"]}'
/root root
[root@study ~]# echo $a
123
[root@study ~]# awk 'BEGIN{print ENVIRON["a"]}'
[root@study ~]# export a
[root@study ~]# awk 'BEGIN{print ENVIRON["a"]}'
123
10.
FILENAME是当前处理文件的文件名
[root@study ~]# awk 'FNR==NR{print FILENAME".txt\t"$0}FNR!=NR{print FILENAME".txt\t"$0}' a b
a.txt a
a.txt b
a.txt c
b.txt c
b.txt d
b.txt e
忽略大小写,等于1表示忽略大小写
[root@study ~]# echo a A b BA |xargs -n1|awk 'BEGIN{IGNORECASE=1}/A/'
a
A
BA
2.
操作符
(....) 分组
$ 字段引用
++ -- 递增和递减
+- ! 加号,减号,逻辑否定
* / %
+ -
| |& 管道,用于getline,print和printf
< > <= >= != ==
~ !~ 正则表达式匹配,否定正则表达式匹配
in 数组成员
&& ||
?:
= += -= *= /= %= ^=变量赋值运算符
在awk中,有3种情况表达式为假:数字是0,空字符串和未定义的值。
数值运算,未定义变量初始值为0。字符运算,未定义变量初始值为空。
截取整数
[root@study ~]# echo "123abc abc456 234abd546"|xargs -n1|awk '{print +$0}'
123
0
234
[root@study ~]# echo "123abc abc456 234abd546"|xargs -n1|awk '{print -$0}'
-123
0
-234
打印奇数行、偶数行
[root@study ~]# seq 6|awk 'i=!i'
1
3
5
[root@study ~]# seq 6|awk '!(i=!i)'
2
4
6
管道符的使用
[root@study ~]# echo 1 3 2 5 6 4|xargs -n1|awk '{print $0|"sort"}'
1
2
3
4
5
6
正则表达式匹配
[root@study ~]# seq 5|awk '$0~3{print $0}'
3
[root@study ~]# seq 5|awk '$0!~3{print $0}'
1
2
4
5
[root@study ~]# seq 5|awk '$0!~/[34]/{print $0}'
1
2
5
[root@study ~]# seq 5|awk '$0~/[34]/{print $0}'
3
4
[root@study ~]# seq 5|awk '$0~/[^34]/{print $0}'
1
2
5
判断数组成员
[root@study ~]# awk 'BEGIN{a["a"]=123}END{if("a" in a)print "yes"}' < /dev/null
yes
三目运算作为一个表达式,里面不允许写print
[root@study ~]# awk 'BEGIN{print 1==1?"yes":"no"}'
yes
替换换行符为逗号
[root@study ~]# seq 5|awk '{print n=n?n","$0:$0}'
1
1,2
1,2,3
1,2,3,4
1,2,3,4,5
[root@study ~]# seq 5|awk '{n=n?n","$0:$0}END{print n}'
1,2,3,4,5
每三行后添加新行
[root@study ~]# seq 10|awk '{print NR%3?$0:$0"\n"}'
1
2
3
4
5
6
7
8
9
10
两行合并到一行
[root@study ~]# seq 6|awk '{printf NR%2!=0?$0" ":$0"\n"}'
1 2
3 4
5 6
[root@study ~]# seq 6|awk '{printf NR%2!=0?$0" ":$0"\n"}'
1 2
3 4
5 6
[root@study ~]# seq 6|awk 'ORS=NR%2?" ":"\n"'
1 2
3 4
5 6
[root@study ~]# seq 6|awk '{if(NR%2)ORS=" ";else ORS="\n";print}'
1 2
3 4
5 6
变量赋值
字段求和
[root@study ~]# seq 5|awk '{sum+=1}END{print sum}'
5
[root@study ~]# seq 5|awk '{sum+=$0}END{print sum}'
15