1.awk的定义
awk是一种编程语言,用于在linux/unix下对文本和数据进行处理。数据可以来自标准输入(stdin)、一个或多个文件,或其它命令的输出。它支持用户自定义函数和动态正则表达式等先进功能,是linux/unix下的一个强大编程工具。它在命令行中使用,但更多是作为脚本来使用。awk有很多内建的功能,比如数组、函数等,这是它和C语言的相同之处,灵活性是awk最大的优势。
2.awk的使用方法
2.1 awk的语法
awk [options] 'script' var=value file(s)
awk [options] -f scriptfile var=value file
2.2 awk的命令常用选项
变量:内置和自
-F fs:fs指定输入分隔符,fs可以是字符串或正则表达式,如-F:
-v var=value:赋值一个用户定义变量,将外部变量传递给awk
-f scripfile:从脚本文件中读取awk命令
-m[fr] val:对val值设置内在限制,-mf选项限制分配给val的最大块数目;-mr选项限制记录的最大数目。这两个功能是Bell实验室版awk的扩展功能,在标准awk中不适用
3.awk变量
定义变量,每个变量前加 -v 命令选项
3.1 内置变量
(1)格式
FS :输入字段分隔符,默认为空白字符
OFS :输出字段分隔符,默认为空白字符
RS :输入记录分隔符,指定输入时的换行符,原换行符仍有效
ORS :输出记录分隔符,输出时用指定符号代替换行符
NF :字段数量,共有多少字段, NF引用最后一列,(NF-1)引用倒数第2列
NR :行号,后可跟多个文件,第二个文件行号继续从第一个文件最后行号开始
FNR :各文件分别计数, 行号,后跟一个文件和NR一样,跟多个文件,第二个文件行号从1开始
FILENAME :当前文件名
ARGC :命令行参数的个数
ARGV :数组,保存的是命令行所给定的各参数,查看参数
[root@along ~]# cat awkdemo
hello:world
linux:redhat:lalala:hahaha
along:love:youou
[root@along ~]# awk -v FS=':' '{print $1,$2}' awkdemo #FS指定输入分隔符
hello world
linux redhat
along love
[root@along ~]# awk -v FS=':' -v OFS='---' '{print $1,$2}' awkdemo #OFS指定输出分隔符
hello---world
linux---redhat
along---love
[root@along ~]# awk -v RS=':' '{print $1,$2}' awkdemo
hello
world linux
redhat
lalala
hahaha along
love
you
[root@along ~]# awk -v FS=':' -v ORS='---' '{print $1,$2}' awkdemo
hello world---linux redhat---along love---
[root@along ~]# awk -F: '{print NF}' awkdemo
2
4
3
[root@along ~]# awk -F: '{print $(NF-1)}' awkdemo #显示倒数第2列
hello
lalala
love
[root@along ~]# awk '{print NR}' awkdemo awkdemo1
1
2
3
4
5
[root@along ~]# awk END'{print NR}' awkdemo awkdemo1
5
[root@along ~]# awk '{print FNR}' awkdemo awkdemo1
1
2
3
1
2
[root@along ~]# awk '{print FILENAME}' awkdemo
awkdemo
awkdemo
awkdemo
[root@along ~]# awk 'BEGIN {print ARGC}' awkdemo awkdemo1
3
[root@along ~]# awk 'BEGIN {print ARGV[0]}' awkdemo awkdemo1
awk
[root@along ~]# awk 'BEGIN {print ARGV[1]}' awkdemo awkdemo1
awkdemo
[root@along ~]# awk 'BEGIN {print ARGV[2]}' awkdemo awkdemo1
awkdemo1
3.2 自定义变量
自定义变量( 区分字符大小写)
(1)-v var=value
① 先定义变量,后执行动作print
[root@along ~]# awk -v name="along" -F: '{print name":"$0}' awkdemo
along:hello:world
along:linux:redhat:lalala:hahaha
along:along:love:you
② 在执行动作print后定义变量
[root@along ~]# awk -F: '{print name":"$0;name="along"}' awkdemo
:hello:world
along:linux:redhat:lalala:hahaha
along:along:love:you
2)在program 中直接定义
可以把执行的动作放在脚本中,直接调用脚本 -f
[root@along ~]# cat awk.txt
{name="along";print name,$1}
[root@along ~]# awk -F: -f awk.txt awkdemo
along hello
along linux
along along
4.操作符
格式
-
算术操作符:
x+y, x-y, x*y, x/y, x^y, x%y -x: 转along"; print为数值
-
字符串操作符:没有符号的操作符,字符串连接
-
赋值操作符:
=, +=, -=, *=, /=, %=, ^= ++a, --a
-
比较操作符:
==, !=, >, >=, <, <=
-
模式匹配符:
~ :左边是否和右边匹配包含 !~ :是否不匹配`
-
逻辑操作符:
与&& ,或|| ,非!
-
函数调用:
function_name(argu1, argu2, ...)
-
条件表达式(三目表达式):
selector ? if-true-expression : if-false-expression
5.awk控制语句
5.1 if-else判断
(1)语法
if(condition){statement;...}[else statement] 双分支
if(condition1){statement1}else if(condition2){statement2}else{statement3} 多分支
(2)使用场景:对awk 取得的整行或某个字段做条件判断
[root@along ~]# awk -F: '{if($3>10 && $3<1000)print $1,$3}' /etc/passwd
operator 11
games 1
[root@along ~]# awk -F: '{if($NF=="/bin/bash") print $1,$NF}' /etc/passwd
root /bin/bash
along /bin/bash
---输出总列数大于3的行
[root@along ~]# awk -F: '{if(NF>2) print $0}' awkdemo
linux:redhat:lalala:hahaha
along:love:you
---第3列>=1000为Common user,反之是root or Sysuser
[root@along ~]# awk -F: '{if($3>=1000) {printf "Common user: %s\n",$1} else{printf "root or Sysuser: %s\n",$1}}' /etc/passwd
root or Sysuser: root
root or Sysuser: bin
Common user: along
---磁盘利用率超过40的设备名和利用率
[root@along ~]# df -h|awk -F% '/^\/dev/{print $1}'|awk '$NF > 40{print $1,$NF}'
/dev/mapper/cl-root 43
---test=100和>90为very good; 90>test>60为good; test<60为no pass
[root@along ~]# awk 'BEGIN{ test=100;if(test>90){print "very good"}else if(test>60){ print "good"}else{print "no pass"}}'
very good
[root@along ~]# awk 'BEGIN{ test=80;if(test>90){print "very good"}else if(test>60){ print "good"}else{print "no pass"}}'
good
[root@along ~]# awk 'BEGIN{ test=50;if(test>90){print "very good"}else if(test>60){ print "good"}else{print "no pass"}}'
no pass
5.2 循环语句
5.2.1 while循环
while``(condition){statement;...}
使用场景
对一行内的多个字段逐一类似处理时使用
对数组中的各元素逐一处理时使用
---以along开头的行,以:为分隔,显示每一行的每个单词和其长度
[root@along ~]# awk -F: '/^along/{i=1;while(i<=NF){print $i,length($i); i++}}' awkdemo
along 5
love 4
you 3
---以:为分隔,显示每一行的长度大于6的单词和其长度
[root@along ~]# awk -F: '{i=1;while(i<=NF) {if(length($i)>=6){print $i,length($i)}; i++}}' awkdemo
redhat 6
lalala 6
hahaha 6
---计算1+2+3+...+100=5050
[root@along ~]# awk 'BEGIN{i=1;sum=0;while(i<=100){sum+=i;i++};print sum}'
5050
5.2.2 do-while循环
do` `{statement;...}``while``(condition)
意义:无论真假,至少执行一次循环体
6.awk数组
6.1 关联数组:array[index-expression]
(1)可使用任意字符串;字符串要使用双引号括起来
(2)如果某数组元素事先不存在,在引用时,awk 会自动创建此元素,并将其值初始化为"空串"
(3)若要判断数组中是否存在某元素,要使用"index in array"格式进行遍历
(4)若要遍历数组中的每个元素,要使用for 循环**:for(var in array)** {for-body}
[root@along ~]# cat awkdemo2
aaa
bbbb
aaa
123
123
123
---去除重复的行
[root@along ~]# awk '!arr[$0]++' awkdemo2
aaa
bbbb
123
---打印文件内容,和该行重复第几次出现 取反不会影响数组中的值 只有在++得时候,值才会改变 ?
[root@along ~]# awk '{!arr[$0]++;print $0,arr[$0]}' awkdemo2
aaa 1
bbbb 1
aaa 2
123 1
123 2
123 3
awk是AWK的命令行工具,它接受一个AWK脚本作为参数,并对输入进行处理。
花括号{}内是AWK脚本的主体,它定义了处理输入数据的操作。
!arr[$0]++:这是一个表达式,它使用了AWK中的数组arr来记录每一行的出现次数。在AWK中,$0表示当前行的全部内容。arr[$0]表示以当前行内容为索引的数组元素。!是逻辑取反操作符,将0转换为1,非0值转换为0。arr[$0]++表示将当前行内容为索引的数组元素自增1,然后返回旧值。所以!arr[$0]++在第一次遇到某一行时为真(1),而后续再次遇到该行时为假(0)。
print $0,arr[$0]:这是一个打印语句,用于输出当前行内容$0以及该行内容在数组中出现的次数arr[$0]。在AWK中,$0表示当前行的全部内容,arr[$0]表示数组中以当前行内容为索引的元素的值。
所以,这段代码的作用是读取文件"awkdemo2",对每一行进行处理,并输出每行内容及其在文件中出现的次数。如果文件中有多个相同的行,则会在输出中显示它们的重复次数
分析:把每行作为下标,第一次进来,相当于print ias...一样结果为空,打印空,!取反结果为1,打印本行,并且++变为不空,下次进来相同的行就是相同的下标,本来上次的值,!取反为空,不打印,++变为不空,所以每次重复进来的行都不打印
awk 关联数组 key=>value 无序
[root@along ~]# awk 'BEGIN{abc["ceo"]="along";abc["coo"]="mayun";abc["cto"]="mahuateng";for(i in abc){print i,abc[i]}}'
coo mayun
ceo along
cto mahuateng
[root@along ~]# awk '{for(i=1;i<=NF;i++)abc[$i]++}END{for(j in abc)print j,abc[j]}' awkdemo2
aaa 2
bbbb 1
123 3