AWK 日常使用总结

上一篇 / 下一篇  2013-05-12 16:58:47 / 个人分类:AWK学习

1.awk中调用系统变量必须用单引号,如果是双引号,则表示字符串
Flag=abcd
awk '{print '$Flag'}'   结果为abcd
awk '{print  "$Flag"}'   结果为$Flag
 
2.BEGIN和END使用:
awk 'BEGIN {print "abin  haha\n============================="}{print $1}END{print "end-if-file"}' cal.txt
3.awk -F '' 可以使用 NULL 为分隔符。

awk -F''  不能使用 NULL 为分隔符。起引号内必须赋值.  
4.每一行开头加"/usr/local"  cat renewlist.txt | awk '{ print "/usr/local"$0}'
 
5.关联数组关联多个字段:
awk 'NR==FNR{a[$3]=$1" "$2}NR>FNR&&b=$6{print $0,a[b]}' b a
 
6.将比较 file1的1-4字符 和 file2的2-5 字符,如果相同,将file2 的第二列 与 file1 合并
awk  'NR==FNR{a[substr($1,2,5)]=$2}NR>FNR&&a[b=substr($1,1,4)]{print $0, a[b]}' a b
 
7.awk调用shell外部函数:
export -f getmacinfo
                awk -v vi="$vi" -v vs="$hostid_ip $vmstate" 'BEGIN{while("getmacinfo '"$vd"'"|getline d){print vi,d,vs}}'

 
8.列求和。
ll -th|awk 'BEGIN{total=0}{total+=$2}END{print total}'
 
9.awk进行数值计算:
echo ""|awk '{print 3+4}'    或者 awk 'BEGIN{print 3+4}'
 
10.打印某字符串对应列:
1)  awk '{for(i=1;i<=NF;i++){if($i=="Country")print i}}' data.txt|xargs -i awk 'NR>1{print ${}}' data.txt



2)  awk '/Country/{for(i=1;i<=NF;i++)if($i~/Country/)a=i}(a){print $a}' data.txt
 

3)打印包含ddga的列
awk 'NR==FNR{for(i=1;i<=NF;i++){if($i=="ddga")a=i}}NR>FNR&&FNR>1{print $a}' aa aa


11.删除第一个字段重复的且第二个字段为0的行:
awk 'NR==FNR{a[$1]++;next}$2!=0||a[$1]==1' test.info test.info
PBCSPOFT0101    96                           
PBCSPOFT0102    6
PBCSPOFT0103    8
PBCSPOFT0104    0
PBCSPOFT0105    0
PBCSPOFT0106    0
PBCSPOFT0107    10
PBCSPOFT0108    0
 
12.a[$1]在未声明之前为假。
 
13、第二次读取同一个文件的时候,a[$1]并不累加,而是直接饮用第一次读取文件的那个值。
awk 'NR==FNR{print NR,$0,a[$1],a[$1]++,a[$1]}NR>FNR{print NR,$0,a[$1]}' test.info test.info
1 PBCSPOFT0101    0                              0 1
2 PBCSPOFT0101    96                             1 1 2
3 PBCSPOFT0102    0  0 1
4 PBCSPOFT0102    6 1 1 2
5 PBCSPOFT0103    0  0 1
6 PBCSPOFT0103    8 1 1 2
7 PBCSPOFT0104    0  0 1
8 PBCSPOFT0105    0  0 1
9 PBCSPOFT0106    0  0 1
10 PBCSPOFT0107    0  0 1
11 PBCSPOFT0107    10 1 1 2
12 PBCSPOFT0108    0  0 1
13 PBCSPOFT0101    0                             2
14 PBCSPOFT0101    96                             2
15 PBCSPOFT0102    0 2
16 PBCSPOFT0102    6 2
17 PBCSPOFT0103    0 2
18 PBCSPOFT0103    8 2
19 PBCSPOFT0104    0 1
20 PBCSPOFT0105    0 1
21 PBCSPOFT0106    0 1
22 PBCSPOFT0107    0 2
23 PBCSPOFT0107    10 2
24 PBCSPOFT0108    0 1
 
 
14.awk可使用shell的重定向符进行重定向输出,如:$ awk '$1 = 100 {print $1 > "output_file" }' test。上式表示如果第一个域的值等于100,则把它输出到output_file中。也可以用>>来重定向输出,但不清空文件,只做追加操作。

15.输出重定向需用到getline函数。getline从标准输入、管道或者当前正在处理的文件之外的其他输入文件获得输入。它负责从输入获得下一行的内容,并给NF,NR和FNR等内建变量赋值。如果得到一条记录,getline函数返回1,如果到达文件的末尾就返回0,如果出现错误,例如打开文件失败,就返回-1。如:

16.$ awk 'BEGIN{ "date" | getline d; print d}' test。执行linux的date命令,并通过管道输出给getline,然后再把输出赋值给自定义变量d,并打印它。

17.$ awk 'BEGIN{"date" | getline d; split(d,mon); print mon[2]}' test。执行shell的date命令,并通过管道输出给getline,然后getline从管道中读取并将输入赋值给d,split函数把变量d转化成数组mon,然后打印数组mon的第二个元素。

18. $ awk 'BEGIN{while( "ls" | getline) print}',命令ls的输出传递给geline作为输入,循环使getline从ls的输出中读取一行,并把它打印到屏幕。这里没有输入文件,因为BEGIN块在打开输入文件前执行,所以可以忽略输入文件。

19. $ awk 'BEGIN{printf "What is your name?"; getline name < "/dev/tty" } $1 ~name {print "Found" name on line ", NR "."} END{print "See you," name "."} test。在屏幕上打印”What is your name?",并等待用户应答。当一行输入完毕后,getline函数从终端接收该行输入,并把它储存在自定义变量name中。如果第一个域匹配变量name的值,print函数就被执行,END块打印See you和name的值。

20. $ awk 'BEGIN{while (getline < "/etc/passwd" > 0) lc++; print lc}'。awk将逐行读取文件/etc/passwd的内容,在到达文件末尾前,计数器lc一直增加,当到末尾时,打印lc的值。注意,如果文件不存在,getline返回-1,如果到达文件的末尾就返回0,如果读到一行,就返回1,所以命令 while (getline < "/etc/passwd")在文件不存在的情况下将陷入无限循环,因为返回-1表示逻辑真。

21. 可以在awk中打开一个管道,且同一时刻只能有一个管道存在。通过close()可关闭管道。如:$ awk '{print $1, $2 | "sort" }' test END {close("sort")}。awd把print语句的输出通过管道作为linux命令sort的输入,END块执行关闭管道操作。

22. system函数可以在awk中执行linux的命令。如:$ awk 'BEGIN{system("clear")'。

23. fflush函数用以刷新输出缓冲区,如果没有参数,就刷新标准输出的缓冲区,如果以空字符串为参数,如fflush(""),则刷新所有文件和管道的输出缓冲区。

24、awk 拆分文件,使用重定向即可:
awk 'NR!=1{print > $6}' netstat.txt

25、模式取反:
awk '!/WAIT/' netstat.txt

TAG:

abinNO1的个人空间 引用 删除 abinNO1   /   2020-08-07 11:35:26
内容:
a INTWMS4
b INTWMS4
a INTWMS3
b INTWMS4
分组求和:
awk '$2~/INTWMS4/{a[$1" "$2]++}END{for (i in a){print i,a[i]}}'
abinNO1的个人空间 引用 删除 abinNO1   /   2019-11-20 15:19:26
1、split 的使用
echo 'abcd as,dsf,b' | awk -F' ' '{len=split($2,a,",");print "length="len}'
abinNO1的个人空间 引用 删除 abinNO1   /   2019-11-10 03:40:00
1、比较 文件中的 第2 和第3列是否相同,相同则打印0 ,不同则打印1
awk  '!NF{next} { if($2==$3) {print"0"} else print"1"}' file
abinNO1的个人空间 引用 删除 abinNO1   /   2016-06-27 13:10:14
原帖由abinNO1于2013-05-21 11:02:54发表
1、定义数组时如果用“a[i]=$1;i++”的形式,其初始值i是为空的即为“null”,即a[ ]=$1;并非是a[0]=$1,.

awk 'NR==FNR{a[i]=$2;b[i]=$1;i++}NR>FNR{if(b[j]==$1){print $0,a[j]}else{print $0};j++}' aa bb
abinNO1的个人空间 引用 删除 abinNO1   /   2016-05-31 22:07:38
更改分隔符:
awk 'BEGIN{FS=",";OFS=" "}{$1=$1;print $0}'
abinNO1的个人空间 引用 删除 abinNO1   /   2013-11-21 15:19:32
1、按照第5个字段排序
awk '{print $0|"sort -k5"}'
abinNO1的个人空间 引用 删除 abinNO1   /   2013-05-30 16:09:50
3、可以将awk中的模式和动作单独写到一个文件中,如定义文件为awk.sh,内容如下:

BEGIN{
        print "\tVMID\t\tVMMAC\n----------------- -----------------"};   #print heading.
        NR==FNR{
                a[$2]++;}
        NR>FNR&&a[$1]==0{
                i++;
                printf "%17s %17s\n",$1,$2;                #formate the datas
                }
        END{
        print "\n" i " rows selected.\n";       #print ending.
}
执行如下命令即可调用改文件:
awk -f awk.sh a b_bak
abinNO1的个人空间 引用 删除 abinNO1   /   2013-05-30 15:58:52
awk对于结构化的文本文件(行列数据)进行复杂的处理,相对于sed而言,还能进行复杂的编程,并且能够产生复杂的输出。

1、例如想输出只在文件b_bak存在而在a文件中没有的第一个字段,找到之后输出整个记录。

awk 'BEGIN{
        print "\tVMID\t\tVMMAC\n----------------- -----------------"};   #print heading.
        NR==FNR{
                a[$2]++;}
        NR>FNR&&a[$1]==0{
                i++;
                printf "%17s %17s\n",$1,$2;             #formate the datas
                }
        END{
        print "\n" i " rows selected.\n";       #print ending.
}' a b_bak

即可输出:

        VMID                VMMAC
----------------- -----------------
VM-20110811-00004 00:16:3e:48:40:88

1 rows selected.

2、想将b_bak中的所有数据按行全部打印出来:

awk '{for(i=1;i<=NF;i++){a[i]=$i; print a[i]}}' b_bak
abinNO1的个人空间 引用 删除 abinNO1   /   2013-05-23 16:38:07
1、删除重复行:

awk '{if ($0!=line) print;line=$0}' ab

awk '!a[$0]++' ab
abinNO1的个人空间 引用 删除 abinNO1   /   2013-05-23 16:31:19
1、将某个文件内容按列打印。
如:
cat a.txt
a
b
c
d
想得到"a b c d",可执行:
awk '{ORS=" ";print }' a.txt
2、将多个文件进行并:
cat b.txt
1
2
3
4
1)将a.txt 和b.txt进行合并得到:
a 1
b 2
c 3
d 4
可以执行:--通过顺序数组来完成
awk 'NR==FNR{a[i]=$0;i++}NR>FNR{print a[j]" "$0;j++}' a.txt  b.txt

也可以执行: --以FNR下标来组成顺序数组完成
awk 'NR==FNR{a[FNR]=$0}NR>FNR{print a[FNR]" "$0;}' a.txt  b.txt

也可以执行:--通过getline来实现
awk '{getline d <"a.txt";print d,$0}' b.txt
3、如果b.txt为: 如果想让a.txt和b.txt合并之后,如果b.txt有一个字段为空就用"NULL"来替换。
cat  b.txt
1
2
3
执行如下语句:
awk 'NR==FNR{a[i]=$0;i++}NR>FNR{if(a[j]==""){print "NULL    "$0}else{print a[j]" "$0};j++}' b.txt  a.txt
既可以得到:
1 a
2 b
3 c
NULL    d
abinNO1的个人空间 引用 删除 abinNO1   /   2013-05-21 11:02:54
1、定义数组时如果用“a[i]=$1;i++”的形式,其初始值i是为空的即为“null”,即a[ ]=$1;并非是a[0]=$1,所以如果后面从0开始调用的时候会漏掉"a[ ]=$1",所以建议从1开始定义数组。

2、如果要求b_bak文件中的第一个字段与a文件中的第二个字段相同的时候,将b_bak中对应的第二个字段紧接到a文件对应行的后面。
下面这种方式就可以得到正确的结果:

awk 'NR==FNR{i++;a[i]=$1;b[i]=$2;c[i]=a[$1]++}NR>FNR{d[m]=e[$2]++;for(j=1;j<i+1;j++){if($2==a[j]&&c[j]==d[m]){print j,b[j],$0,c[j],m,d[m];break}};m++}'   b_bak a

说明:数组c[i]保存的是文件第一个字段重复的次数即a[$1]++

3、上面的情况就不能使用关联数组来做。
使用关联数组的时候要注意:
1)当关联的字段有重复的时候,被关联的对象如果不一样,多个文件进行关联的时候,被关联的对象就会被覆盖:

如 aa文件:
aa ddga
aa dddd
dd gaga

bb文件:
aa haha
aa cccc
cc xixi
要求:得到如下的结果:
aa haha ddga
aa cccc dddd
cc xixi

如果用如下形式就会有问题:
awk 'NR==FNR{a[$1]=$2}NR>FNR&&b=$1{print $0,a[$1]}' aa bb

得到了:
aa haha dddd
aa cccc dddd
cc xixi

此时需要用数组去关联:
awk 'NR==FNR{i++;a[i]=$1;b[i]=$2;c[i]=a[$1]++}NR>FNR{d[m]=e[$1]++;for(j=1;j<i+1;j++){if(a[j]==$1&&c[j]==d[m]){print $0,b[j];break}else if(a[j]!=$1){print $0;break}};m++}' aa bb



原帖由abinNO1于2013-05-20 17:29:50发表
数组关联
1、cat b_bak a

VM-20111104-00001 00:16:3e:48:40:84
VM-20110520-00006 00:16:3e:48:40.
abinNO1的个人空间 引用 删除 abinNO1   /   2013-05-20 17:29:50
数组关联
1、cat b_bak a

VM-20111104-00001 00:16:3e:48:40:84
VM-20110520-00006 00:16:3e:48:40:85
VM-20110520-00006 00:16:3e:48:40:86
VM-20110811-00003 00:16:3e:48:40:87
VM-20110811-00004 00:16:3e:48:40:88
VM-20110816-00007 00:16:3e:7d:b0:ba
VM-20110816-00007 00:16:3e:48:40:81
VM-20110816-00006 00:16:3e:48:40:82
VM-20111104-00001 00:16:3e:48:40:83
c3rn.vrs.0.vm.i-1a15d7089  VM-20110816-00007 10.71.192.117   192-168-1-109-20110815035415  "C_01"   "blade9"
c3rn.vrs.0.vm.i-1a15d7089  VM-20110816-00007 10.1.0.59       192-168-1-109-20110815035415  "C_01"   "blade9"
c3rn.vrs.0.vm.i-1a15d7087  VM-20110816-00006 10.1.0.58       192-168-1-109-20110815035415  "C_02"   "blade10"
c3rn.vrs.0.vm.i-1a15d7014  VM-20111104-00001 10.71.184.77    192-168-2-17-20110121024432   "C_05"   "blade13"
c3rn.vrs.0.vm.i-1a15d7014  VM-20111104-00001 10.1.0.82       192-168-2-17-20110121024432   "C_05"   "blade13"
c3rn.vrs.0.vm.i-1a15d7017  VM-20110520-00006 10.71.184.150   192-168-2-17-20110121024432   "C_05"   "blade13"
c3rn.vrs.0.vm.i-1a15d7017  VM-20110520-00006 10.0.0.108      192-168-2-17-20110121024432   "C_05"   "blade13"
c3rn.vrs.0.vm.i-1a15d7010  VM-20110811-00003 10.71.184.101   192-168-1-18-20110328121943   "C_05"   "blade10"

2、awk 'NR==FNR{a[i]=$1;b[i]=$2;c[i]=a[$1]++;i++}NR>FNR{d[m]=e[$2]++;while(j<i){if($2==a[j]&&c[j]==d[m]){print j,b[j],$2,c[j],m,d[m];break}j++}m++}' b_bak a
abinNO1的个人空间 引用 删除 abinNO1   /   2013-05-15 10:07:31
1、cat aa bb
aa haha
bb dddd
cc
aa haha
bb cccc
cc
2、打印bb上有,aa上没有的第二个字段:
awk 'NR==FNR{a[$2]++}NR>FNR&&a[$2]!=1{print $2}' aa bb
abinNO1的个人空间 引用 删除 abinNO1   /   2013-05-14 20:35:18
1、关联数组的另一种等效写法。
cat a b
c3rn.vrs.0.vm.i-1a15d7089  VM-20110816-00007 10.71.192.117   192-168-1-109-20110815035415  "C_01"   "blade9"
c3rn.vrs.0.vm.i-1a15d7089  VM-20110816-00007 10.1.0.59       192-168-1-109-20110815035415  "C_01"   "blade9"
VM-20110816-00007 00:16:3e:7d:b0:ba
VM-20110816-00007 00:16:3e:48:40:81

awk 'NR==FNR{a[i]=$1" "$3" "$4" "$5" "$6;i++}NR>FNR{print $0,a[j];j++}' a b
 

评分:0

我来说两句

Open Toolbar