awk命令用法

  awk:把文件逐行的读入,以空格为默认分隔符将每行切片,切开的部分再进行各种分析处理,是一个强大的文本分析工具,在对数据分析并生成报告时很有优势。

  awk有3个不同版本: awk、nawk和gawk,未作特别说明,一般指gawk,gawk 是 AWK 的 GNU 版本。

  • 命令格式:
    awk [options] 'program' FILE ...
其中:
    options:
        -F:指明输入时用到的字段分隔符,默认空白字符;
        -v:指定变量
        -v var=value:自定义变量
    program:
        PATTERN{ ACTION STATEMENTS;...} (语句之间用 ; 分隔)
        PATTERN--模式,这意味着并不是对文件中的每一行进行处理,而是处理那些能够被模式匹配到的行,不跟模式表示全文;
        ACTION--常见的处理机制是打印,命令有print和printf.
  • 变量
    • 常见内置变量  
  FS:切割时的分隔符,默认为空白字符;
  OFS:切割后输出时的分隔符,默认为空白字符;
  RS:输入时的换行符,默认为'\n';
  ORS:输出时的换行符,默认为'\n';
  NF:字段数量 ( $NF表示最后一个字段);
  NR:行数;
  FNR:分别计算各文件的行数;
  FILENAME:当前文件名;
  ARGC:命令行参数的个数;
  ARGV:数组,保存的是命令行所给定的各参数
示例:
   awk -v FS=: '{print $1}' /etc/passwd (相当于awk -F: "{print $1}" /etc/passwd)
   awk -v FS=: -v OFS=, '{print $1,$2}' /etc/passwd
   awk -v RS=' ' '{print}' /etc/issue
   awk '{print NF}' /etc/fstab (可对比 awk '{print $NF}' /etc/fstab,$NF表示最后一个字段)
   awk 'BEGIN{print ARGC}' /etc/fstab /etc/issue (命令行参数有3个,分别为awk,/etc/fstab,/etc/issue)
   awk 'BEGIN{print ARGV[#]}' /etc/fstab /etc/issue (#表示索引下标)
    • 自定义变量
种方式可自定义变量:
    (1) -v var=value
    (2) 在program中直接定义
示例:
  awk -v test="hello gawk" 'BEGIN{print test}' (相当于awk 'BEGIN{test="hello gawk";print test}')
  • 打印输出
    • print
    print item1,item2,...
示例:
tail -5 /etc/fstab | awk '{print $2,$4}' ($1..$#:内置变量,表示分隔后的字段)
tail -5 /etc/fstab | awk '{print "hello:",$2,$4}' (注意,{}只能由单引号'' 引起来,不能用双引号"")
要点:
    (1) 逗号,作为不同字段的分隔符;
    (2) item可以是字符串,数值,当前记录的字段、变量或awk的表达式;
    (3) 如省略item,相当于print $0(打印所有元素;$0表示所有字段)
    • printf
格式化输出:printf FORMAT,item1,item2,...
释义:
(1) FORMAT必须给出;
(2) 不会自动换行,需要显式给出换行控制符,'\n';
(3) FORMAT中需要分别为后面的每个item指定一个格式化符号;
        格式符:
                %c:显示字符的ASCII码;
                %d,%i:显示十进制整数;
                %e,%E:科学计数法数值显示;
                %f:显示为浮点数;
                %g,%G:以科学计数法或浮点形式显示数值;
                %s:显示字符串;
                %u:无符号整数;
                %%:显示%自身
        修饰符:
                #[.#]:第一个数字控制显示的宽度;第二个#表示小数点后的精度
示例:
  %-3.1f,其中 '-' 表示左对齐;%+5.2d,其中 '+' 会显示数值的符号
  awk -F: '{printf "Uername:%s, UID:%d\n",$1,$3}' /etc/passwd
  awk -F: '{printf "Uername:%-15s, UID:%d\n",$1,$3}' /etc/passwd
  •  操作符
  算术操作符:x+y,x-y,x*y,x/y,x^y(多少次方),x%y
  赋值操作符:=,+=,-=,*=,/=,%=,^=,++,--
  比较操作符:>,>=,<,<=,!=,==
  模式匹配符:~:是否匹配;!~:是否不匹配
  逻辑操作符:&&,||,!
  函数调用:function_name(argu1,argu2,...)
  条件表达式:selector ? if-true-expression : if-false-expression
示例:
  awk -F: '{$3>=1000?usertype="Common User":usertype="Sysadmin or SysUser";printf "%15s : %-s\n",$1,usertype}' /etc/passwd
  awk '!/^UUID/{print $0}' /etc/fstab
  awk -F: '$3>1000{print $1,$3}' /etc/passwd
  awk -F: '$NF~/bash$/{print $1,$NF}' /etc/passwd
  • PATTERN
(1) /regular expression/:仅处理被模式匹配到的行;
(2) relational expression:关系表达式,为"真"时处理 ("真":结果是非0值或非空字符串);
(3) line ranges:行范围 (startline, endline 或 /pat1/, /pat2/);
    注意: 此处行范围不支持直接给出数字的格式
    示例:
  awk -F: '(NR>=2&&NR<=10){print $1}' /etc/passwd
  awk -F: '/^h/,/^s/{print $1}' /etc/passwd (4) BEGIN/END模式: BEGIN{}: 仅在开始处理文件中的文本之前执行一次; END{}:仅在文本处理完成之后执行一次 示例:
  head /etc/passwd | awk -F: 'BEGIN{print "username uid"}{printf "%-12s%-5s\n",$1,$3}END{printf "%10s\n","END"}'
  • 控制语句
    • if-else
语法:
    if(condition) statement [else statement]
使用场景:
    对awk取得的整行或某个字段做条件判断.
示例:
    awk -F: '{if($3>=1000) {printf "Common user: %s\n",$1} else {printf "root or Sysuser: %s\n",$1}}' /etc/passwd
    awk -F: '{if($NF=="/bin/bash") print $1}' /etc/passwd
    awk '{if(NF>5) print $0}' /etc/fstab
    df -h | awk -F% '/^\/dev/{print $1}' | awk '{if($NF>=20) print $1}'
    • while and do while
语法:
    while(condition) statement (条件"真"时进入循环;条件"假"时退出循环)
    do statement while(condition) (至少执行一次循环体)
使用场景:
    对一行内的多个字段逐一处理时使用;对数组中的各元素逐一处理时使用.
示例:
    awk '/^[[:space:]]*linux16/{i=1;while(i<=NF) {print $i,length($i); i++}}' /etc/grub2.cfg
    awk '/^[[:space:]]*linux16/{i=1;while(i<=NF) {if(length($i)>=7) {print $i,length($i)}; i++}}' /etc/grub2.cfg
    • for
语法:
    for(expr1;expr2;expr3) statement
    for(variable assignment;condition;iteration process) {for-body}
示例:
    awk '/^[[:space:]]*linux16/{for(i=1;i<=NF;i++) {print $i,length($i)}}' /etc/grub2.cfg
特殊用法:遍历数组中的元素
    语法:for(var in array) {for-body}
    • switch
语法:
    switch(expression) {case VALUE1 or /REGEXP/: statement; case VALUE2 or /REGEXP2/: statement; ...; default: statement}
    • break and continue
break:终止循环
continue:中断本次循环继续下一轮
    • next
提前结束对本行的处理而直接进入下一行;
示例:
    awk -F: '{if($3%2!=0) next; print $1,$3}' /etc/passwd
  • array数组
1) 关联数组:
    array[index-expression]
    index-expression:
        ① 可使用任意字符串;字符串要使用双引号;
        ② 如果某数组元素事先不存在,在引用时,awk会自动创建此元素,并将其值初始化为"空串"
2) 若要判断数组中是否存在某元素,要使用"index in array"格式进行;
3) 若要遍历数组中的每个元素,要使用for循环:for(var in array) {for-body}
示例:
    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
    awk '/^UUID/{fs[$3]++}END{for(i in fs){print i,fs[i]}}' /etc/fstab
    awk '{for(i=1;i<=NF;i++){count[$i]++}}END{for(i in count){print i,count[i]}}' /etc/fstab
    netstat -tan | awk '/^tcp\>/{state[$NF]++}END{for(i in state){print i,state[i]}}'
  • 内置函数
    rand():返回0和1之间一个随机数;
    length([s]):返回指定字符串的长度;
    sub(r,s,[t]):以r表示的模式来查找t所表示的字符中的匹配的内容,并将其第一次出现替换为s所表示的内容;
    gsub(r,s,[t]):以r表示的模式来查找t所表示的字符中的匹配的内容,并将其所有出现均替换为s所表示的内容;
    split(s,a,[r]):以r为分隔符切割字符s,并将切割后的结果保存至a所表示的数组中
示例:
    netstat -tan | awk '/^tcp\>/{split($5,ip,":");count[ip[1]]++}END{for(i in count){print i,count[i]}}'
    awk '/^[[:space:]]*kernel/{i=1;while(i<=NF){if(length($i)>=7)print $i,length($i);i++}}' /etc/grub.conf

猜你喜欢

转载自www.cnblogs.com/walk1314/p/9077590.html