文本三剑客之awk

Posted 三千繁华01

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了文本三剑客之awk相关的知识,希望对你有一定的参考价值。

awk总结

(一)awk模式扫描和处理语言

  基本用法:
    awk [options] ‘program‘ var=value file...
    awk [options] -f programfile var=value file...
    awk [options] ‘BEGIN{action;....} pattern{action;...} END{action;....}‘ file...

  program:通常是被双引号或单引号引起的

  选项:
    -F :知名输入时用到的字符分割段。
    -v var=value : 自定义变量
  program:pattern{action statements;...}
  patten和action:
    pattern 决定动作语句何时触发及触发事件,包括BEGIN ,END语句
    action statements:对数据进行处理,放在{}内指明print,printf

  分隔符,域和记录:
    awk执行时,由分隔符分割的字段称为域标记$1,$2..$n称为标示域。其中$0为所有域,注意此种$和shell中含义不同
    所读取的文件的每一行称为记录
    如果省略action,则默认执行print $0的操作
     

 [[email protected] ~]# awk ‘{print "hello,awk"}‘ /etc/fstab
 [[email protected] ~]# awk ‘{print }‘ /etc/fstab

  


  awk的工作原理:
    (1)执行BEGIN{action...}语句块中的语句
    (2)从文件或者标准输入读取一行,然后执行pattern{action;...}语句块,它逐行扫描文件,从第一行到最后一行指导文件被读取完毕。
    (3)当渎至输入流末尾时执行END{action;...}语句块

  print的格式:print #,#,#.....
     (1)多个#用逗号分隔
     (2)输出可以是字符串也可以是数值。
     (3)如果省略相当于print $0


  注意: (1)BEGIN语句在awk开始从输入流中读取行之前被执行,是一个可选语句块,比如变量初始化,打印出表格的表头等语句通常可以写在BEGIN语句块中。
      (2)END是在输入完之后被读取执行的,所以可以把结果写在其语句块中。
      (3)pattern 语句块中通用的命令是最重要的部分,也是可选的。如果没有提供pattern语句块,则默认执行{print},即打印每一个读取到的行

awk -F: ‘{print $1}‘ /etc/passwd
[[email protected] ~]# awk -F: ‘{print $1, $3}‘ /etc/passwd
[[email protected] ~]# awk BEGIN‘{print "hellow,word"}‘
[[email protected] ~]# awk ‘END{print "hellow,word"}‘ /etc/fstab END需要有文件。
hellow,word

 

(二)awk的内置变量
    FS:输入字段分隔符,默认为空白字符

[[email protected] ~]# awk -v FS=‘:‘ ‘{print $1,$3}‘ /etc/passwd 只指定输入字段分隔符为‘:’
awk -v FS=‘:‘ ‘{print $1,FS,$3}‘ /etc/passwd 指定输入输出分隔符都为“:”
[[email protected] ~]# awk -F: ‘{print $1,$3}‘ /etc/passwd 不指定输出分隔符时为默认输出空白分割符。

    OFS:输出字段分隔符,默认为空白字符

[[email protected] ~]# awk -v FS=‘:‘ -v OFS=‘@‘ ‘{print $1,$3}‘ /etc/passwd 指定了输入和输出分割符。
[email protected]
[email protected]
[email protected]
[email protected]
[[email protected] ~]# awk -F: -v OFS=‘@‘ ‘{print $1,$3}‘ /etc/passwd 此用法同上一条。

   RS:输入记录分隔符,指定输入时的换行符,原换行符仍有效 默认记录分隔符时回车。

[[email protected] app]# cat /app/asd 
11.222:444:555:
6666:2543:9527:
3333:1:3
[[email protected] app]# awk -v RS=: ‘{print }‘ /app/asd
11.222
444
555

6666
2543
9527

3333
1
3

  

  ORS:输出记录分隔符,输出时用指定的符号代替换行符。

@[[email protected] app]# cat /app/asd
a 11.222:444:555:
b 66 66:25.43:9527:
3333:1:3
[[email protected] app]# awk -v RS=: -v FS=. -v ORS="@" ‘{print $1}‘ /app/asd
a [email protected]@[email protected]
b 66 [email protected]@[email protected]
[email protected]@3
解释:输入分隔符为“:”,然后以“.”为记录分隔符 ,最后以@为输出分隔符输出第一列。

  NF:字段数量

[[email protected] app]# awk -F: ‘{print NF}‘ /etc/passwd 
7
7
7
7
7
[[email protected] app]# awk -F: ‘{print $(NF-1)}‘ /etc/passwd 引用内置变量不用$

  显示每一个记录中有多少个字段,并将其统计结果输出。
  NR:行号

[[email protected] app]# awk ‘{print NR}‘ /etc/passwd 打印行号

[[email protected] app]# awk ‘END{print NR}‘ /etc/passwd 打印总行数。

  FNR:各文件分别计数,行号

[[email protected] app]# awk ‘{print FNR}‘ /etc/passwd /etc/fstab

  FILENAME:当前文件名:

[[email protected] app]# awk ‘{print FILENAME}‘ /etc/fstab
/etc/fstab
/etc/fstab
/etc/fstab

  

  ARGC:命令行参数的个数

[[email protected] app]# awk ‘BEGIN{print ARGC}‘ a b c d 其中awk也算一个命令参数。
5

  

  ARGV:数组,保存的是命令行所给定的各参数

[[email protected] app]# awk ‘BEGIN{print ARGV[1]}‘ a b c d
a
[[email protected] app]# awk ‘BEGIN{print ARGV[2]}‘ a b c d
b
[[email protected] app]# awk ‘BEGIN{print ARGV[0]}‘ a b c d
awk

  

(三)awk中自定义变量
    (1)-v var=value
    (2) 在program 中直接定义

[[email protected] app]# awk -v test="hello ,word" ‘BEGIN{print test}‘ 
hello ,word

[[email protected] app]# awk ‘BEGIN{test="hello word";print test}‘ 
hello word

[[email protected] app]# awk -F: ‘{sex="male";print $1,sex,age;age=18}‘ /etc/passwd
root male 
bin male 18
daemon male 18

可以看出变量的位置不懂是会影响输出结果的。

也可以写在文件里:
[[email protected] app]# cat asd 
{age=18;sex="male";print $1,sex,age}
[[email protected] app]# awk -F: -f asd /etc/passwd
root male 18
bin male 18
daemon male 18

  

(四)printf 格式化输出:
    (1)必须制定FORMAT
    (2)不会自动换行,需要给出换行符,\n
    (3)FORMAT中需要分别为后面的每一个item制定格式符

    格式符:
      %c :显示字符的ASCII码
      %d %i:显示十进制整数
      %e %E :显示科学计数法数值
      %f :显示浮点数
      %g %G :以科学计数法或浮点形式显示数值
      %s :显示字符串
      %u :无符号整数
      %% :显示%自身
  修饰符:
      #[.#]:第一个数字控制显示的宽度;第二个#表示小数点后的精度,%3.1f
      - : 左对齐(默认为右对齐) %-20s
      + : 显示数值的正负符号%+d

[[email protected] app]# awk -F: ‘{printf "%-20s %10d\n",$1,$3}‘ /etc/passwd
root 0
bin 1
daemon 2

[[email protected] app]# awk -F: ‘{printf "username:%-20s UID:%10d\n",$1,$3}‘ /etc/passwd
username:root UID: 0
username:bin UID: 1
username:daemon UID: 2

[[email protected] app]# awk -F: ‘{printf "username:%-20s UID:%-10d\n",$1,$3}‘ /etc/passwd
username:root UID:0 
username:bin UID:1 
username:daemon UID:2

(五)操作符:

  算术操作符:
      x+y,x-y,x*y,x/y,x^y,x%y
    -x:转换为负数
    +x:转换为数值
  字符串操作符:
      = ,+= ,-= ,*= ,/= , %= ,^= ,++ , --
  比较操作符:
      == ,!= ,> ,>= ,< , <=
  模式匹配符:~ :左边是否和右边匹配包含 !~ :是否不匹配

[[email protected] app]# awk -F: ‘$0 ~ "^root" {print $1}‘ /etc/passwd
root

[[email protected] app]# awk ‘$0 !~ /root/‘ /etc/passwd
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
adm:x:3:4:adm:/var/adm:/sbin/nologin

[[email protected] ~]# seq 10 |awk ‘{if($1%2==0){print $1}}‘ 
2
4
6
8
10

  

  逻辑操作符:
      与&& , 或|| , 非!
  三目表达式:
      x>y?x=y:y=x

[[email protected] ~]# awk -F: ‘$3>1000 && $3<=3000 {print $1,$3}‘ /etc/passwd
liubei 1001
[[email protected] ~]# awk -F: ‘$3>3000 || $3<=5 {print $1,$3}‘ /etc/passwd
[[email protected] ~]# awk -F: ‘!($3>10) {print $1,$3}‘ /etc/passwd

[[email protected] ~]# awk -F: ‘$3<1000?usertype="systemuser":usertype="common user"{printf "user:%-20s %s %s\n" ,$1, "is", usertype}‘ /etc/passwd

  

  PATTERN:根据pattern条件,过滤匹配的行,再做处理
      (1)如果未指定,控模式则会匹配每一行
      (2)/regular expression/:仅处理能够被模式匹配到的行,需要用/ / 括起来
 

   ~#]awk‘/^UUID/{print $1}’/etc/fstab

[[email protected] ~]# awk ‘/^[[:blank:]]*UUID/ {print $1}‘ /etc/fstab

  


      (3)relational expression :关系表达式,结果为真才会被处理
        真:结果为非零值,非空字符串
        假:结果为空字符串或0值

  

[[email protected] ~]# seq 10 |awk ‘0‘
[[email protected] ~]# seq 10 |awk ‘1‘
1
2

[[email protected] ~]# seq 10 |awk ‘i=!i‘
1
3
5
7
9

[[email protected] ~]# seq 10 |awk ‘!(i=!i)‘
2
4
6
8
10

  

      (4)line ranges:行范围
          格式: awk ‘/pat1/,/pat2/{}‘ file 此格式不知持直接给出数字格式

[[email protected] ~]# awk -F: ‘/^sync/,/^o/{print $1}‘ /etc/passwd 
sync
shutdown
halt
mail
operator
[[email protected] ~]# awk -F: ‘(NR>=10 && NR<=20){print NR,$1}‘ /etc/passwd

  

      (5)BEGIN/END模式

        BEGIN{}:仅在开始处理文件中的文本之前执行一次
        END{}:仅在文本处理完成之后执行一次 

[[email protected] ~]# awk -F: ‘BEGIN{print "username salar\n--------------------------------"}{printf "%-20s %-10s\n" ,$1,$3}{sum+=$3}END{print "pingjungongzi:" sum/NR}‘ /etc/passwd

 (六)action的常用分类 

      (1)算数比较表达式
      (2)if while 等循环语句
      (3)组合语句
      (4)输入
      (5)输出

  awk中的控制语句if-else

      语法:if(控制条件){statement;...}[else statement]
      if(condition1){statement;...}if(condition2){statement;...}else{statement;...}
      使用场景:对awk取得的整行或某个字段做条件判断

[[email protected] ~]# df -h |awk -F% ‘/^\/dev\/sd[[:lower:]][[:digit:]]\>/{print $1}‘|awk ‘$NF>50{printf "%-10s %s\n",$1,$5}‘

[[email protected] ~]# awk -F: ‘{if($3<1000){level="low"}else if($3<3000 && $3>1000){level="Soso"}else{level="High"};printf "%-20s%-10s%s\n",$1,$3,level }‘ /etc/passwd

  

  awk中的控制语句while循环:
      语法:while(condition){statement;...}
      条件为真时进入循环,条件为假时退出循环
      使用场景:
        对一行内的多个字段逐一类似处理使用
        对数组中的各元素逐一处理时使用

[[email protected] app]# awk ‘/^[[:space:]]+linux16/{n=1;while(n<NF){print $n,length($n);n++}}‘ /app/grub2.cfg

  

  do-while循环
      语法:do{statement;...}while(condition)
      意义:无论真假,至少执行一次循环体

[[email protected] app]# awk ‘BEGIN{sum=0;i=1;do{sum+=i;i++}while(i<=100);print sum}‘

[[email protected] app]# echo {1..10} |awk ‘{i=1;while(i<=NF){if($i%2==0){print $i, "is oushu"}else{print $i, "is jishu"};i++}}‘

  

  for循环:
      语法:for(expr1;expr2;expr3){statement;...}
      常见用法:
        for(variable assignment;condition;iteration process)
        {for-body}
      特殊用法:能够遍历数组中的元素
        语法:for(var in array){for-body}

[[email protected] app]# awk ‘/^[[:space:]]+linux16/{for(i=1;i<=NF;i++){print $i,length($i)}}‘ /app/grub2.cfg

[[email protected] app]# time seq -s "+" 1000000|bc
500000500000

real	0m0.421s
user	0m0.212s
sys	0m0.252s

[[email protected] app]# time awk ‘BEGIN{for(i=1;i<=1000000;i++){sum+=i}{print sum}}‘
500000500000

real	0m0.094s
user	0m0.092s
sys	0m0.002s

[[email protected] app]# time ( sum=0; for (( i=0;i<=1000000;i++ ));do let sum+=i;done;echo $sum)
500000500000

real	0m6.469s
user	0m6.203s
sys	0m0.264s

  

  switch语句:
      语法:switch(expression){case VALUE1 or /REGEXP/:statement1;case VALUE2 or /REGEXP2/:statement2;...;default:statementn}
      break和continue next
      break:结束循环,continue:跳出本次循环 next:提前结束对本行的处理而直接进入下一行处理。

[[email protected] app]# awk -F: ‘{if($3%2!=1){next};print $1,$3}‘ /etc/passwd 打印奇数行。

 

(七)awk数组
    关联数组:array[index-expression]
      (1)可使用任意字符串,字符串要使用双引号括起来
        (2)如果某数组元素实现不存在,在引用时,awk会自动创建此元素,并将其值初始化为“空串”

  若要判断数组中是否存在某元素,要使用“index in array”格式进行遍历

[[email protected] app]# awk ‘BEGIN{weekday["mon"]="monday";weekday["tue"]="tuesday";weekday["thr"]="thrsday";for (n in weekday){print n,weekday[n]}}‘

[[email protected] ~]# awk ‘{ip[$1]++}END{for(n in ip){print n, ip[n]}}‘ /root/access_log 统计日志中每一个IP访问的次数

[[email protected] ~]# netstat -tan |awk ‘/^tcp/{state[$NF]++}END{for(n in state){print n,state[n]}}‘
ESTABLISHED 1
LISTEN 11
[[email protected] ~]# awk -F: ‘!shuzu[$0]++‘ /etc/passwd 利用awk函数实现去除重复项

 

  

(八)awk 函数
  数值处理:
      rand():返回0和1之间一个随机数:可以用它来显示一个十,一百等以内的随机整数

[[email protected] ~]# awk ‘BEGIN{srand();for (n=0;n<1;n++){print int(rand()*100)}}‘

  

    length([s]):返回指定字符串的长度

    gsub(r,s,[t]):对字符串进行搜索r表示的模式匹配的内容,并全部替换为s所表示的内容。

[[email protected] ~]# echo "2018:3:31/15:34:31" |awk -F/ ‘gsub(":","-",$1)‘
2018-3-31 15:34:31
[[email protected] ~]# echo "2018:3:31/15:34:31" |awk ‘gsub(":","-",$1)‘
2018-3-31/15-34-31

  


    split(s,arry,[r]):以r为分隔符,切割字符串s,并将切割的结果保存至arry所表示的数组中第一个索引值为一,第二个索引值为2,......

[[email protected] ~]# netstat -tan |awk ‘/^tcp\>/{split($5,ips,":");count[ips[1]]++}END{for (n in count){print n,count[n]}}‘

  


  自定义函数
      格式:function name (parameter,....){


          statements

          return expression
        }

[[email protected] lianxi321]# awk -v a=200 -v b=30 -f funct_1.awk 
200
[[email protected] lianxi321]# cat funct_1.awk 
#!/bin/awk -f
function max(v1,v2){
v1>v2?var=v1:var=v2
return var
}
BEGIN{print max(a,b)}



[[email protected] lianxi321]# cat test.awk 
#!/bin/awk -f
{ print $1,$3 }
[[email protected] lianxi321]# ./test.awk -F: /etc/passwd

  



以上是关于文本三剑客之awk的主要内容,如果未能解决你的问题,请参考以下文章

文本处理三剑客之AWK

文本三剑客之awk

文本处理三剑客之gawk

linux 文本三剑客之awk

文本三剑客之awk进阶篇

文本三剑客之awk