awk常用参数

-F 指定分隔符
-v 指定变量和默认值
$NF 代表最后一个字段
NR 代表第几行
&&
$ (NF- (n-1)) 取倒数第n列
FS 输入分隔符,与-F分隔符一样
OFS 输出字段分隔符
RS 输入记录分隔符
$0 显示整行
1…N 第一个字段到第N个字段

awk参数具体玩法

-F 指定分隔符

tail -1 /etc/passwd | awk -F ":" '{print $6}' #指定分隔符“:”并截取第六个字段
awk -F'[ :]' '{print $2,$4}' #指定两个记录分隔符(空格和:)
awk -F'[ :]+' '{print $2,$4}'  #多一个加号表明将连续出现的记录分隔符当做一个来处理
在awk中,当记录分隔符指定为空字符串时,awk会将多个连续的空白看做一个单一的记录分隔符。此外,awk还会忽略开头和结尾处的空白。

awk -F'one|two' '{for(i=1;i<=NF;i++)print i,"="$i}'  #分隔符是个字符串

运行结果:

img

-v 指定变量和默认值

seq 1 10 > 1.txt #生成一个1到10的文件,我想计算出文件内的总和

awk -v “a=0” ‘{a+=$1;print a}’ 1.txt | tail -1 #给a赋值为0,让a与文件内的第一个字段相加,最后结果通过tail 打印出来 但是看的出来很麻烦

##优先级END 下面会有讲

awk -v “a=0” ‘{a+=$1}END{print a}’ 1.txt

$NF代表最后一个字段

awk -F ":" 'NR==10{print $NF}' /etc/passwd ##截取/etc/passwd文件下面的第10行,最后一个字段

NR 选行

awk NR==44'{print $0}' /etc/passwd #打印/etc/passwd下的第44行,$0代表整行

&&与

条件1 && 条件2 都要满足才为真,真返回1,假返回0

awk -v "a=0" 'NR==1{print (a+=$1 > 10) && (a+=$2 >10)}' 2.txt ##如果条件为假则返回0

awk -v "a=0" 'NR==1{print (a+=$1 < 10) && (a+=$2 <10)}' 2.txt ##如果为真返回 1

||或

条件1 || 条件2 ##条件满足一边 为真

awk -v 'a=0' 'NR==1{print (a+=$1 >10) || (a+=$2 < 10)}' 2.txt #两个条件都不满足,返回假,也就是0

awk -v 'a=0' 'NR==2{print (a+=$1 >10) || (a+=$2 < 10)}' 2.txt #第二行,两边条件满足一遍,所以结果为1

FS指定分隔符

#没有优先级写法
awk '{FS=":"}NR==2{print $1,$2}' 3.txt
#优先级写法
awk 'BEGIN{FS=":"}NR==2{print $1,$2}' 1.txt

OFS一般与FS或者-F共同使用

awk -F ":" 'NR==2{OFS="_";print $1,$2}' 1.txt  #指定分隔符":",OFS中间的间隔换成你指定的

awk 'BEGIN{FS=":";OFS="-"}NR==2{print $1,$2,$3}' 1.txt #FS用法与上面意思相同

RS指定结尾符一般与OFS配合

写法单独写RS:

awk 'BEGIN{RS=""}{print $0}' 2.txt ##在文本操作的时候结尾默认是回车(\n),RS指定结尾符号

RS与OFS配合使用写法:

注意 如果是$0的话,不会有效果,单独使用是可以,如果配合OFS使用就不能是整行

awk 'BEGIN{RS="";OFS="##"}{print $1,$2,$3}' 2.txt  ##RS指定结尾符,OFS指定链接符

#也可以指定特殊符号
awk 'BEGIN{RS="";OFS="\n"}{print $1,$2,$3}' 2.txt

awk之优先级

最高:BEGIN是最高优先级,是在执行PROGRAM之前执行的,不需要提供数据源,因为不涉及任何数据,也不依赖PROGRAM代码块;

默认:PROGRAM是对数据流干什么,是必选代码块,也是默认代码块。所以执行的时候必须要加上数据源; 默认优先级(不加优先级就是默认)

最低:END是处理完数据流后,如果需要执行END代码块,就必须要PROGAM的支持,单个无法执行

 注意:如果只用最高或者最低优先级,后面跟上数据源(file)不会有效果,只有默认优先级PROGRAM才会有效果

最高优先级 BEGIN

##写法一

awk 'BEGIN{print "zhangsan"}'   #BEGIN后面不需要加任何数据源,也可以打印内容

##写法二(赋值写法)

awk 'BEGIN{a[1]="zhangsan";a[2]="28";print a[1],a[2]}' #将a[1],a[2]赋值,并打印

awk 'BEGIN{name="zhangsan";age="28";print name,age}'  #与上面同理

默认优先级PROGRAM(对数据源操作)

比如我想计算机内存使用率(总内存 - 空闲 *100 / 总内存)
awk 'NR==1{a=$2}NR==2{b=$2;print(a-b)*100/a"%"}' /proc/meminfo   #将总内存赋值给a,空闲内存赋予b ,在利用算法算出内存使用率,最后加入一个“%”看起来好看

END最低优先级

对数据处理的最后一个值

seq 1 10  > 1.txt #生成一个1到10 的文件

awk -v "a=0" '{a+=$1}END{print a}' 1.txt #$1代表第一个字段,将第一个字段的所有数相加

我们把第一个字段加起来了,会发现很多数值,我们就要最后一个结果,我们就加上END看两者的区别

awk之模糊匹配

比如说我想看我的用户信息,我就记得用户是gx开头的,我不打开文件下,我们可以这么做:

awk -F ":" '$1 ~ "gx"{print $0}' /etc/passwd  #注意“~”匹配查询,后面关键字要用引号引起来一定要双引号 
#$1代表第一个字段,可以写成别字段比如第二字段就是$2...

#匹配多个写法
awk -F ":" '$1 ~"gx"{print $0};$1 ~ "roo"{print $0}' /etc/passwd

awk命令之控制流写法

awk之if判断语句

if(condition){statement;…}[else statement]  双分支
if(condition1){statement1}else if(condition2){statement2}else{statement3}  多分支

awk '{if($1>5)print $1*$2;else print $1/$2}' 2.txt #如果$1大于5,$1乘以$2,否则$1除以$2

awk之for循环

awk '{a=0;for(i=1;i<11;i++){a+=$i}print a}' 2.txt  ##初始化值a,然后内容有几行循环就几次,最后将字段相加,就是结果了

awk之while循环

awk '{a=0;b=1;while(b<10){a+=$b;b++}print a}' 2.txt  #单条语句写法

##逐行写法
awk '{
sum=0
i=1
while (i<11) {
sum+=$i
i++
}
print sum 
}' 2.txt
运行结果:

awk之do…while写法

awk '{a=0;b=1;do{a+=$b;b++}while (b<11)print a}' 2.txt  #do...while 就是将写在while中的语句拿出来写,最后while循环

##多行写法
awk '{
a=0
b=1
do{
a+=$b
b++}
while (b<11)
print a}' 2.txt

awk数组

语法

arrayname[string]=value

arrayname是数组的名字
string是数组的下标
alue是数组中任何元素的值

访问数组元素

如果你想访问数组中的值,可以通过它的下标访问,就像arrayname[index],这样会返回给你数组中那个下标对应的值。如果你想访问数组中所有的元素,可以使用循环访问数组的所有的下标,就像下面:
for (var in arrayname)
actions
var是任何变量的名字
in是一个关键字
arrayname是数组的名字
actions是要执行的语句列表。如果你想执行多条语句,必须放在大括号中。
这个循环对每一个数组中的元素执行acctions列表中的操作。

删除数组元素

如果你想删除数组中特定下标的元素,使用Awk删除语句。一旦删除了Awk数组中的元素,就不能再恢复。
delete arrayname[index]

    下面的循环语句从数组中删除所有的元素。没有能删除数组中所有元素的单条语句。你不得不通过循环和使用Awk的删除语句删除每个元素。
for (var in arrayname)
delete arrayname[var]

实际的Awk数组例子

所有的例子都是用这个Iplogs.txt文件,这个文件包括了网关服务器所需要的ip地址列表,文件中的数据符合下面的格式:

cat Iplogs.txt
180607 093423    123.12.23.122 133
180607 121234    125.25.45.221 153
190607 084849   202.178.23.4 44
190607 084859   164.78.22.64 12
200607 012312    202.188.3.2 13
210607 084849   202.178.23.4 34
210607 121435    202.178.23.4 32
210607 132423    202.188.3.2 167

列出所有的IP地址和它被请求的次数

awk '{Ip[$3]++} END {for (var in Ip) print var, "accessed", Ip[var], "times"}' Iplogs.txt
123.12.23.122 accessed 1 times
164.78.22.64 accessed 1 times
202.188.3.2 accessed 2 times
125.25.45.221 accessed 1 times
202.178.23.4 accessed 3 times
  • 第三个域($3)是一个IP地址,用来作为Ip数组的下标
  • Ip[$3]++ 表示每次遇到一个 IP 地址时,其计数加 1
  • 遍历 Ip 数组中的每个元素。输出每个 IP 地址及其访问次数。

results matching ""

    No results matching ""