AWK 专家必备的12个技巧

  • 2020 年 3 月 13 日
  • 筆記

AWK 专家必备的12个技巧案例1:字符切割案例2:格式化输出案例3:不显示文件最后一行案例4:不显示最后一列案例5:多列求和案例6:求每行最大值/最小值/平均值案例7:awk的三元表达式案例8:打印第一列相同且第二列最大的行案例9:多列比较求最大值案例10:除第一列外所有值求和案例11:构建不同文件相同列的映射关系案例12:行列调换/矩阵转换案例13:不同文件相同字段匹配至同一个文件,空字段补齐

AWK 专家必备的12个技巧

案例1:字符切割

  • 方法1:index函数

知识点: #index 简介➔ Index(s,t) 返回子串t在字符串s中的位置,如果没有指定s,返回0

awk '  BEGIN{  ##定义变量x  x="abc def";  ##awk中变量直接引用,无需$引用  part=index(x,"b");  ##打印从b位置开始后的4个字符-包括b位置  print substr(x,part,4)  }'

结果:

  • 方法2:substr函数

知识点: substr简介➔Substr(s,p,n) 返回字符串s中从位置p开始长度为n的子串.如果没有给出n,返回从p开始剩余的字符串

awk '  BEGIN{  ##定义变量x  x="1234567";  ##打印从第二个字符开始所有字符  part1=substr(x,2);  print part1,"..."  }'    awk 'bash  BEGIN{  x="1234567";  ##打印从第二个字符开始,后3个字符  part1=substr(x,2,3);  print part1,"..."  }'

结果:

案例2:格式化输出

知识点: printf()函数

# cat ../test_tem/grade  john 10 3  78 94 88  andrea 20 90 75 90 86  jasper 90 150 90 92 84  apple  90 85 76 90 87  sun    60 50 80 98 87  month  100 120 130 80 90  sam   90 85 78 92 90      # cat my_student_avg  BEGIN{ OFS = "t"  format="|%-8s|t|%-8s|t|%-6s|t|%-2s|n"  print "*******************************************************"  printf format,"name","S_total","S_avg","grade"  print "*******************************************************"  }  {      student_total=0      for (i=2;i<=NF;i++){        student_total+=$i        total+=$i        avg=student_total/(NF-1)        student_avg[NR]=avg      }        #student_avg[NR]=student_total/(NF-1)      if (avg>=90) grade="A"        else if (avg>=80) grade="B"        else if (avg>=70) grade="C"        else if (avg>=60) grade="D"        else grade="F"        ++class_grade[grade]        printf  format,$1,student_total,avg,grade  #student_avg[NR]      #print "__________________"      #print "avg:",avg,"bbbbbbskdljflkflsjgkl"  }    END{      for (x=1;x<=NR;x++){        class_total_avg+=student_avg[x]        class_avg=class_total_avg/NR      }      for (y=1;y<=NR;y++){        print "student:",student_avg[y],"class_avg",class_avg        if (student_avg[y]>class_avg)          ++above_average        else          ++below_average      }        for (same_grade_sort in class_grade){        print same_grade_sort ":",class_grade[same_grade_sort]|"sort"      }          #print  "END:class_total_avg:",class_total_avg      print  "END:class_avg:",class_avg      print  "END:above_average:",above_average      print  "END:below_average:",below_average    }

结果:

案例3:不显示文件最后一行

知识点: 内置函数巧用

awk 'NR != 1' file

案例4:不显示最后一列

  • 方法1:循环方式:
awk 'BEGIN{OFS="";ORS=""}{for(i=1;i<NF;i++){printf  $i" "}{print "n"}}'  file
  • 方法2:非循环方式
awk 'NF--{print NF}' file

案例5:多列求和

知识点: 二维数组

# cat file  85 92 78 94 88  89 90 75 90 86  84 88 90 92 84    awk '  {                            ##主体函数以"{"开始  for(i=1;i<NF;i++)            ##设置循环体,     {a[NR]+=$i}               ##赋值到数组,  }                            ##主体函数"}"闭合  END{                         ##END函数  for(i in a)                  ##读取数组     {print i,a[i]}            ##打印数key,及value  }' file

结果

案例6:求每行最大值/最小值/平均值

  • 求每行最大值
awk '  {                             ##主体函数以"{"开始  max=-65535                  ##设变量max[awk会自动判断变量类型]  for(i=1;i<=NF;i++)            ##设置循环体,     {max=($i>max)? $i:max}  ##awk 三元表达式 如果$i>max 则max=$i,否则max=max  print max                     ##打印出来max  }' file

结果

  • 求每行最小值
awk '  {min=65535;  for(i=1;i<=NF;i++)     {min=($i<min)? $i:min};  print min  }' file

结果

案例7:awk的三元表达式

知识点: 三元表达式 awk '{print ($1<$2) ? "true" : "false"}'

结果

案例8:打印第一列相同且第二列最大的行

知识点: 三元表达式

awk '  {  a[$1]=(a[$1]>$2)?a[$1]:$2                   ####三元表达式  }END{  for(i in a)    {print i,a[i]}  }' d

结果

案例9:多列比较求最大值

知识点: 二维数组&三元表达式

awk '  {  max=0;  for(i=1;i<=NF;i++)    {max=($i>max)? $i:max}    ;print max  }' file

结果

案例10:除第一列外所有值求和

awk '  {  for(i=2;i<=NF;i++)    {a[$1]+=$i}  }END{  for(i in a)    {print i,a[i]}  }' grade

结果

案例11:构建不同文件相同列的映射关系

知识点: 没有知识点,多练~

awk '  NR==FNR {a[$2]=$1}  NR>FNR && ($4 in a){print $1,$2,$3,a[$4],$5  }' replace  ../test_tem/ruku_conf_tmp    # cat replace  001 1  002 2  009 9  010 10  031 31  015 15  008 8  007 7  006 6  039 39  040 40  032 32  036 36  037 37    # cat ../test_tem/ruku_conf_tmp  10.158.143.22 pass 10.158.148.36 1 10.158.145.12  10.158.143.23 pass 10.158.148.36 2 10.158.145.13  10.158.143.24 pass 10.158.148.36 9 10.158.145.14  10.158.143.92 pass 10.158.150.17 10 10.158.145.15  10.158.168.11 pass 10.158.150.17 15 10.158.145.16  10.158.168.12 pass 10.158.150.17 31 10.158.145.17  10.158.164.28 pass 10.158.150.16 32 10.158.145.25  10.158.164.27 pass 10.158.150.16 36 10.158.145.36  10.158.143.25 pass 10.158.147.20 37 10.158.145.24  10.158.164.29 pass 10.158.150.19 39 10.158.146.26  10.158.164.30 pass 10.158.150.19 40 10.158.146.27

结果

案例12:行列调换/矩阵转换

需求如图:

处理

awk '  BEGIN{min=0};  NR==FNR{cc[$2]=$1};  NR>FNR&&($1 in cc){a[$1]=(min>$2)?min:$2  }END{  for(i in a)    if(i in cc)      {print  i,a[i]}  }' cainhe1 cainhe2

结果

案例13:不同文件相同字段匹配至同一个文件,空字段补齐

awk 'NR==FNR{a[$1]=$2};NR>FNR{a[$1]?a[$1]=a[$1]" "$2:a[$1]=a[$1]" $ "$2}END{for(i in a){print i,a[i]}}' ../test_tem/e ../test_tem/c

结果: