AWK运用

awk:报告生成器,格式化文本输出
        有多种版本:New awk (nawk ),GNU awk(gawk)
gawk:模式扫描和处理语言
基本用法:
awk [options] ‘program’ var=value file…
awk [options] -f programfile var=value file…
awk [options] ‘BEGIN{ action;… } pattern{ action;… } END{action;… }’ file …
awk 程序通常由:BEGIN语句块、能够使用模式匹配的通用语句块、END语句块,共3部分组成
program 通常是被单引号或双引号;尽量使用单引号
  选项:
       -F  指明输入时用到的字段分隔符
       -v  var=value:

基本格式:awk [options] ‘program’ file…
   program:pattern{action statements;..}
   pattern 和action: :
? pattern 部分决定动作语句何时触发及触发事件BEGIN,END
? action statements 对数据进行处理,放在{} 内指明print, printf分割符、域和记录
? awk 执行时,由分隔符分隔的字段(域)标记$1,$2..$n称
  为域标识。$0 为所有域,注意:和shell 中变量$ 符含义不同
? 文件的每一行称为记录
? 省略action行 ,则默认执行 print $0的操作

awk工作原理:
第一步:执行BEGIN{action;… } 语句块中的语句
第二步:从文件或标准输入(stdin) 读取一行,然后执行pattern{action;… } 语句块,
            它逐行扫描文件,从第一行到最后一行重复这个过程,直到文件全部被读取完毕。
第三步:当读至输入流末尾时,执行END{action;…}语句块BEGIN 语句块在awk开始从输
            入流中读取行之前被执行,这是一个可选的语句块,比如变量初始化、打印输出表
           格的表头等语句通常可以写在BEGIN 语句块中
END 语句块在awk 从输入流中读取完所有的行之后即被执行,比如打印所有行的分析
      结果这类信息汇总都是在END 语句块中完成,它也是一个可选语句块
pattern 语句块中的通用命令是最重要的部分,也是可选的。如果没有提供pattern 
            语句块,则默认执行{ print } ,即打印每一个读取到的行,
            awk 读取的每一行都会执行该语句块

print 格式:print item1, item2, …
  要点:
? (1)  逗号分隔符
? (2)  输出的各item 可以字符串,也可以是数值;当前记录的字段、
变量或awk 的表达式
? (3)  如省略item ,相当于print $0
  示例:
awk ‘{print “hello,awk”}’  file
awk –F: ‘{print}’ /etc/passwd
awk –F: ‘{print “wang”}’ /etc/passwd
awk –F: ‘{print $1}’ /etc/passwd
awk –F: ‘{print $0}’ /etc/passwd
awk –F: ‘{print $1”\t”$3}’ /etc/passwd
tail –3 /etc/fstab |awk ‘{print $2,$4}’

awk变量:内置和自定义变量
 FS :输入字段分隔符,默认为空白字符
      awk -v FS=’:’ ‘{print $1,FS,$3}’ /etc/passwd
      awk –F: ‘{print $1,$3,$7}’ /etc/passwd
 OFS :输出字段分隔符,默认为空白字符
      awk -v FS=‘:’ -v OFS=‘:’ ‘{print $1,$3,$7}’ /etc/passwd
 RS :输入记录分隔符,指定输入时的换行符,原换行符仍有效
      awk -v RS=’ ‘ ‘{print }’ /etc/passwd
 ORS :输出记录分隔符,输出时用指定符号代替换行符
      awk -v RS=’ ‘ -v ORS=’###’‘{print }’ /etc/passwd
 NF :字段数量
      awk -F:‘{print NF}’ /etc/fstab, 引用内置变量不用$
      awk -F: ‘{print $(NF-1)}’ /etc/passwd
 NR :行号
      awk ‘{print NR}’ /etc/fstab ; awk END‘{print NR}’ /etc/fstab

FNR :各文件分别计数, 行号
    awk ‘{print FNR}’ /etc/fstab /etc/inittab
FILENAME :当前文件名
    awk ‘{print FILENAME}’ /etc/fstab
ARGC :命令行参数的个数
    awk ‘{print ARGC}’ /etc/fstab /etc/inittab
    awk ‘BEGIN {print ARGC}’ /etc/fstab /etc/inittab
ARGV :数组,保存的是命令行所给定的各参数
      awk ‘BEGIN {print ARGV[0]}’ /etc/fstab /etc/inittab
      awk ‘BEGIN {print ARGV[1]}’ /etc/fstab /etc/inittab

printf命令:
格式化输出:printf  “FORMAT ”, item1, item2, …
(1)  必须指定FORMAT
(2)  不会自动换行,需要显式给出换行控制符,\n
(3)  FORMAT 中需要分别为后面每个item 指定格式符
     格式符:与item 一一对应
%c:  显示字符的ASCII码 码
%d, %i:  显示十进制整数
%e, %E: 显示科学计数法数值
%f :显示为浮点数
%g, %G :以科学计数法或浮点形式显示数值
%s :显示字符串
%u :无符号整数
%%:  显示% 自身
  修饰符:

[.#] :第一个数字控制显示的宽度;第二个# 表示小数点后精度,%3.1f

–   :  左对齐(默认右对齐) %-15s                                           #加上负号表示左对齐
      +   :显示数值的正负符号 %+d
exam:
? awk -F: ‘{printf “%s”,$1}’ /etc/passwd
? awk -F: ‘{printf “%s\n”,$1}’ /etc/passwd
? awk -F: ‘{printf “%-20s %10d\n”,$1,$3}’ /etc/passwd
? awk -F: ‘{printf “Username: %s\n”,$1}’ /etc/passwd
? awk -F: ‘{printf “Username: %s,UID:%d\n”,$1,$3}’ /etc/passwd
? awk -F: ‘{printf “Username: %15s,UID:%d\n”,$1,$3}’ /etc/passwd
? awk -F: ‘{printf “Username: %-15s,UID:%d\n”,$1,$3}’ /etc/passwd

算术操作符:
x+y, x-y, xy, x/y, x^y, x%y
-x:  转换为负数
+x:  转换为数值
   字符串操作符:没有符号的操作符,字符串连接
   赋值操作符:
            =, +=, -=, *=, /=, %=, ^=
            ++, —
  比较操作符:
            ==, !=, >, >=, <, <=
  模式匹配符:~ :左边是否和右边匹配包含 !~ :是否不匹配
        awk –F: ‘$0 ~ /root/{print $1}‘ /etc/passwd    #整行包括root就打印
        awk ‘$0~“^root”‘ /etc/passwd                   #行首包含root
        awk ‘$0 !~ /root/‘ /etc/passwd
        awk –F: ‘$3==0’ /etc/passwd
        awk -F: ‘$3==1000{print $1,$3}’ /etc/passwd    #一个等号是赋值,2个比较

逻辑 操作符:与&& ,或|| ,非!  
   示例:
? awk –F: ‘$3>=0 && $3<=1000 {print $1}’ /etc/passwd
? awk -F: ‘$3==0 || $3>=1000 {print $1}’ /etc/passwd
? awk -F: ‘!($3==0) {print $1}’ /etc/passwd
? awk -F: ‘!($3>=500) {print $3}’ /etc/passwd      #取反需要小括号
  函数调用: function_name(argu1, argu2, …)
  条件表达式(三目表达式):
selector?if-true-expression:if-false-expression
      #为真就执行第一个命名,为假执行第二个命令
? 示例:
      awk -F: ‘{$3>=1000?usertype=”Common User”:usertype=”Sysadmin”;printf 
               “%15s:%-s\n”,$1,usertype}’ /etc/passwd

PATTERN: 根据pattern 条件,过滤匹配的行,再做处理
(1) 如果未指定:空模式,匹配每一行
(2) /regular expression/ :仅处理能够模式匹配到的行,需要用/ /括起来
      awk ‘/^UUID/{print $1}’ /etc/fstab
      awk ‘!/^UUID/{print $1}’ /etc/fstab
(3) relational expression:  关系表达式,结果为“真”才会被处理
    真:结果为非0 值,非空字符串          #“0”表示有字符串0,为真
    假:结果为空字符串或0值               #0为假 ,0以外的都是真
    示例:
? awk -F: ‘i=1;j=1{print i,j}’ /etc/passwd   #i=1;分号单独打印了,用,就代表一起
? awk ‘!0’ /etc/passwd ; awk ‘!1’ /etc/passwd  
? awk –F: ‘$3>=1000{print $1,$3}’ /etc/passwd
? awk -F: ‘$3<1000{print $1,$3}’ /etc/passwd
? awk -F: ‘$NF==”/bin/bash”{print $1,$NF}’ /etc/passwd
? awk -F: ‘$NF ~ /bash$/{print $1,$NF}’ /etc/passw
(4) line ranges   : 行范围   也支持贪婪模式
    startline,endline :/pat1/,/pat2/  不支持直接给出数字格式
    awk -F: ‘/^root\>/,/^nobody\>/{print $1}’  /etc/passwd
    awk -F: ‘(NR>=10&&NR<=20){print NR,$1}’    /etc/passwd
(5) BEGIN/END 模式
      BEGIN{}:  仅在开始处理文件中的文本之前执行一次
      END{} :仅在文本处理完成之后执行一次
      seq 10|awk ‘i=!i’ :当i=1的时候打印第一行,循环到第二行时候1取反等于0
                          不打印第二行,第三行0取反为真,打印第三行,打印奇数行
      seq 10 |sed -n ‘1~2p’

awk控制语句:
 { statements;… }  组合语句
 if(condition) {statements;…}
 if(condition) {statements;…} else {statements;…}
 while(conditon) {statments;…}
 do {statements;…} while(condition)
 for(expr1;expr2;expr3) {statements;…}
 break
 continue
 delete array[index]
 delete array
 exit

语法:if(condition){statement;…}[else statement]
      if(condition1){statement1}else if(condition2){statement2}
      else{statement3}                #条件和语句一起使用,条件用()
    使用场景:对awk 取得的整行或某个字段做条件判断
    完整的语句之间使用不要用使用;号   {}中使用;号
    示例:
awk -F: ‘{if($3>=1000)print $1,$3}’ /etc/passwd
awk -F: ‘{if($NF==”/bin/bash”) print $1}’ /etc/passwd
awk ‘{if(NF>5) print $0}’ /etc/fstab
awk -F: ‘{if($3>=1000) {printf “Common user: %s\n”,$1} else
         {printf “root or Sysuser: %s\n”,$1}}’ /etc/passwd
awk -F: ‘{if($3>=1000) printf “Common user: %s\n”,$1;
         else printf “root or Sysuser: %s\n”,$1}’ /etc/passwd
df -h|awk -F% ‘/^\/dev/{print $1}’|awk ‘$NF>=80{print $1,$5}‘
awk ‘BEGIN{ test=100;if(test>90){print “very good”}
        else if(test>60){ print “good”}else{print “no pass”}}’

while 循环
  语法:while(condition){statement;…}
  条件“真”,进入循环;条件“假”,退出循环
  使用场景:
        对一行内的多个字段逐一类似处理时使用
        对数组中的各元素逐一处理时使用
  示例:
      awk ‘/^[[:space:]]
linux16/{i=1;while(i<=NF)       #NF字段数
            {print $i,length($i); i++}}’ /etc/grub2.cfg
      awk ‘/^[[:space:]]linux16/{i=1;while(i<=NF) {if(length($i)>=10)
            {print $i,length($i)}; i++}}’ /etc/grub2.cfg
  length:统计有几个字符,awk自带的函数‘
      akw ‘BEGIN{print length(“aaaaaaaaa”)}’  #统计有几个a

do-while 循环
  语法:do {statement;…}while(condition)
  意义:无论真假,至少执行一次循环体                 #意思是先执行再循环
  示例:
? awk ‘BEGIN{ total=0;i=0;do{
      total+=i;i++;}while(i<=100);print total}‘
  思考:下面两语句有何不同?
? awk ‘BEGIN{i=0;print ++i,i}’          #先赋值,再打印
? awk ‘BEGIN{i=0;print i++,i}’          #先打印i 再赋值

 for 循环
  语法:for(expr1;expr2;expr3) {statement;…}
  常见用法:
for(variable assignment;condition;iteration process){for-body}
  特殊用法:能够遍历数组中的元素;
语法:for(var in array) {for-body}
  示例:
   awk ‘/^[[:space:]]
linux16/{for(i=1;i<=NF;i++) {print$i,length($i)}}’ 
                                                              /etc/grub2.cfg

1到100相加的几种方法:awk效率最高
 time (awk ‘BEGIN{
              total=0;for(i=0;i<=10000;i++){total+=i;};print total;}’)
 time(total=0;for i in {1..10000};do total=$(($total+i));done;echo $total)
 time(for ((i=0;i<=10000;i++));do let total+=i;done;echo $total)
 time(seq –s ”+” 10000|bc)           #-s指定分隔符,默认是换行

switch 语句
  语法:switch(expression) {case VALUE1 or /REGEXP/:
      statement1; case VALUE2 or /REGEXP2/: statement2; …; default: statementn}
   break 和continue
? awk ‘BEGIN{sum=0;for(i=1;i<=100;i++)  {if(i%2==0)continue;sum+=i}print sum}‘
? awk ‘BEGIN{sum=0;for(i=1;i<=100;i++)  {if(i==66)break;sum+=i}print sum}‘
   break [n]
 continue [n]
 next:  提前结束对本行处理而直接进入下一行处理(awk 自身循环)
          awk -F: ‘{if($3%2!=0) next; print $1,$3}’ /etc/passwd

关联数组:array[index-expression]
          index-expression:
? (1) 可使用任意字符串;字符串要使用双引号括起来
? (2) 如果某数组元素事先不存在,在引用时,awk会自动创建此元素,
      并将其值初始化为“空串”
?  若要判断数组中是否存在某元素,要使用“index in array”格 式进行遍历
   示例:
? weekdays[“mon”]=”Monday“
? awk ‘BEGIN{weekdays[“mon”]=”Monday”; 
       weekdays[“tue”]=”Tuesday”;print weekdays[“mon”]}‘
? awk ‘!arr[$0]++’ dupfile         #出现重复的$0 加1但是不再打印  和uniq -c 类似
? awk ‘{!arr[$0]++;print $0, arr[$0]}’ dupfile
  若要遍历数组中的每个元素,要使用for 循环
   for(var in array) {for-body}
   注意:var 会遍历array 的每个索引
   示例:
? awk ‘BEGIN{weekdays[“mon”]=”Monday”;weekdays[“tue”]=”Tuesday”;for(i in 
        weekdays) {print weekdays[i]}}‘
? netstat -tan | awk ‘/^tcp/{state[$NF]++}END {for(i in state)
         { print i,state[i]}}’
? awk ‘{ip[$1]++}END{for(i in ip) {print i,ip[i]}}’  /var/log/httpd/access_log

数值处理:
      rand() :返回0 和1 之间一个随机数
          awk ‘BEGIN{srand(); for (i=1;i<=10;i++)print int(rand()*100) }’
字符串处理:
? length([s])  : 返回指定字符串的长度
? sub(r,s,[t]) : 对t 字符串进行搜索r 表示的模式匹配的内容,
                  并将第一个匹配的内容替换为s
          echo “2008:08:08 08:08:08” | awk ‘sub(/:/,“-“,$1)’
? gsub(r,s,[t]) :对t 字符串进行搜索r 表示的模式匹配的内容,并全部替换
                为s 所表示的内容
          echo “2008:08:08 08:08:08” | awk ‘gsub(/:/,“-“,$0)’
? split(s,array,[r]) :以r 为分隔符 ,切割字符串s ,并将切割后的结果保存
  至array所表示的 数组中,第一个索引值为1, 第二个索引值为2,…
          netstat -tan | awk ‘/^tcp\>/{split($5,ip,”:”);count[ip[1]]++}
          END{for (i in count) {print i,count[i]}}’

自定义函数
  格式:
function name ( parameter, parameter, … ) {
            statements
            return expression
}
  示例:

cat fun.awk

function max(v1,v2) {                  #函数名和参数(形参)
      v1>v2?var=v1:var=v2              #三目表达式
      return var                       #函数的值就是var
}
BEGIN{a=3;b=2;print max(a,b)}          #实参

awk –f fun.awk                        #-f 调用awk函数

system 命令               #awk中可以调用shell命令
  空格是awk 中的字符串连接符,如果system 中需要使用awk中
    的变量可以使用空格分隔,或者说除了awk 的变量外其他一律用”” 引用起来。
           awk BEGIN‘{system(“hostname”) }’
           awk ‘BEGIN{score=100; system(“echo your score is ” score) }’

将awk 程序写成脚本,直接调用或执行
  示例:

cat f1.awk

if($3>=1000)print $1,$3}

awk -F: -f f1.awk /etc/passwd

cat f2.awk

#!/bin/awk –f
    #this is a awk script
        {if($3>=1000)print $1,$3}

chmod +x f2.awk

f2.awk –F: /etc/passwd

格式:
  awkfile var=value var2=value2… Inputfile      #在脚本外面传递参数        
  注意 :在BEGIN 过程中不可用。直到首行输入完成以后,变量才可用。可以通过-v参数,
  让awk 在执行BEGIN 之前得到变量的值。命令行中每一个指定的变量都需要一个-v 参数
   示例:

cat test.awk

#!/bin/awk –f
    {if($3 >=min && $3<=max)print $1,$3}
        #chmod +x test.awk
        #test.awk -F: min=100 max=200 /etc/passw    
      这里的赋值可以再print里面使用,再BEGIN和END里面需要-v min=200
      但是建议习惯使用-v不管如何都能使用,免得遗忘

时间: 2024-11-08 22:17:46

AWK运用的相关文章

新awk整理

总感觉上一篇awk的总结几乎是照着man翻译过来的,惨不忍睹 无意间在互联网上有找到了宝贵的资料 感觉整理的很好,想着照着这个来重新写下,对照新的man更新下吧,只是总是在改变的 一.awk简介二.awk工作流程三.awk程序结构四.awk基本语法 awk命令行模式 awk程序文件 awk标准选项五.awk内置变量 标准awk变量 awk特定变量(即专有变量)六.awk操作符 算数运算符 关系运算符 逻辑运算符 三元运算符 一元运算符 字符串连接操作符(即空格符) 数组成员操作符(in) 正则表

linux提取指定列字符并打印所有内容(awk)

假设有文件长如下样子: CHROM  POS     ID      REF     ALT     QUAL    FILTER  INFO    FORMAT  samplename 1 3552841 . G . 32.995 . DP=1;MQ0F=0;AF1=0;AC1=0;DP4=1,0,0,0;MQ=40;FQ=-29.9912 GT:PL:DP 0/0:0:1 1 3552842 . T . 32.995 . DP=1;MQ0F=0;AF1=0;AC1=0;DP4=1,0,0,0

shell之awk

简介 awk是一个强大的文本分析工具,相对于grep的查找,sed的编辑,awk在其对数据分析并生成报告时,显得尤为强大.简单来说awk就是把文件逐行读入,以空格为默认分割符将每行切片,切开的部分再进行各种分析处理. 使用方法: awk [option] 'pattern1{action1}pattern2{action2}' {filenames} 尽管操作可能会很复杂,但语法总是这样,其中pattern表示awk在数据中查找的内容,而action是在找到匹配内容时所执行的一系列命令. awk

awk中使用shell变量

其实在awk里,是不能直接使用shell变量的 方法是:awk -v 选项让awk 里使用shell变量 TIME=60 awk -v time="$TIME" 'BEGIN{FS="|"} {if ($7>time) print $2 }' 这样要注意:在awk里,time不能加$符号. 网上说如下方法都可行: 一:"'$var'" 这种写法大家无需改变用'括起awk程序的习惯,是老外常用的写法.如: var="test&quo

awk 字符串处理函数

awk提供了许多强大的字符串函数,见下表:awk内置字符串函数gsub(r,s)    在整个$0中用s替代rgsub(r,s,t)    在整个t中用s替代rindex(s,t)    返回s中字符串t的第一位置length(s)    返回s长度match(s,r)    测试s是否包含匹配r的字符串split(s,a,fs)    在fs上将s分成序列asprint(fmt,exp)    返回经fmt格式化后的expsub(r,s)    用$0中最左边最长的子串代替ssubstr(s,

awk

cat 1.txt 1 2 3 4 5 6 7 8 9 1 2 3 4 5 6 7 8 9 1 2 3 4 5 6 7 8 9 行转列: awk '{for(i=1;i<=NF;i++)printf("%s\n",$i)};{printf "\n"}' 1.txt 显示如下: 1 2 3 4 5 6 7 8 9 1 2 3 4 5 6 7 8 9 1 2 3 4 5 6 7 8 9

如何在linux Shell脚本里面把一个数组传递到awk内部进行处理

前段时间和几位同事讨论过一个问题:Shell脚本里面怎样把一个数组传递到awk内部进行处理? 当时没有找到方法.前两天在QQ群里讨论awk的时候,无意间又聊起这个话题.机缘巧合之下找到一个思路,特此分享. 测试环境: [root]# head -1 /etc/redhat-release Red Hat Enterprise Linux Server release 6.5 (Santiago) [root]# awk --version | head -1 GNU Awk 3.1.7 众所周知

Linux文本处理三剑客之GNU awk的使用

awk: Aho, Weinberger, Kernighan,报告生成器,格式化文本输出 有多种版本:New awk(nawk),GNU awk(gawk) gawk –模式扫描和处理语言 基本用法: awk[options] 'program' var=value file- awk[options] -f programfile var=value file- awk[options] 'BEGIN{ action;... } pattern{ action;... } END{ acti

第4章 awk编程

1 awk编程模型       2 awk用法 调用awk有三种方法(与sed类似): 在Shell命令行输入命令调用awk,格式为: awk [-F 域分隔符] 'awk程序段' 输入文件 将awk程序段插入脚本文件后,然后通过awk命令调用它: awk -f awk脚本文件输入文件 将awk命令插入脚本文件后,最常用的方法是设置该脚本文件为可执行,然后直接执行该脚本文件,格式为: ./awk脚本文件输入文件 注:第二种方法脚本文件的首行不以#!/bin/awk –f开头:第三种方法脚本文件的

awk: (FILENAME=- FNR=1) 致命错误: 试图访问字段 -2

执行:awk '{print $(NF-2)}' aa.log 出现错误:awk: (FILENAME=aa.log FNR=1) 致命错误: 试图访问字段 -2 可能和aa.log中数据有关系: 改为: awk 'NF>1{print $(NF-2)}' aa.log