zoukankan      html  css  js  c++  java
  • Linux-awk命令详解

    awk 命令详解

      awk 是一种编程语言,用于在linux/nuix下对文本和数据进行处理。数据可以来自标准输入、一个或多个文件,或其它命令的输出。它支持用户自定义函数和动态正则表达式等先进功能,是linux/unix下的一个强大的编程工具。它在命令行中使用,但更多是作为脚本来使用。

      awk 的处理文本和数据的方式是这样的,它逐行扫描文件,从第一行到最后一行,寻找匹配的特定模式的行,并在这些行上进行你想要的操作。如果没有指定处理动作,则把匹配的行显示到标准输出(屏幕),如果没有指定模式,则所有被操作所指定的行都被处理。awk分别代表其作者姓氏的第一个字母。因为它的作者是三个恩,分别是Alfred Aho、Brian Kernighan、Peter Weinberger。gawk是awk的GNU版本,它提供了Bell实验室和GNU的一些扩展。

    awk命令两种使用方式:

      (1)命令行模式:awk [options] 'commands' file(s)

      (2)脚本模式:awk [options] -f scriptfile file[s]

    awk 命令模式

    awk [options] 'commands' file(s) 
    
    option:
        -F 定义字段分割符号
        -v 定义变量并赋值
    command:
        1、范围说明或者正则表达式或者{awk命令语句1;awk命令语句2;}
        2、范围说明部分可以是BEGIN、END、逻辑表达式或者为空
        3、awk命令语句间用分号间隔
        4、引用shell变量时需要用双引号引起,命令模式都在单引号''里面
        
        BEGIN{}    {}        END{}
        行处理前     行处理    行处理后
    
    命令格式:
    awk 'pattern' filename               示例:awk '/root/' /etc/passwd
    awk '{action}' filename              示例:awk -F: '{print $1}' /etc/passwd
    awk 'pattern {action}' filename      示例:awk -F: '/root/{print $1,$3}'    /etc/passwd          
    示例:awk 'BEGIN{FS=":"} /root/{print $1,$3}' /etc/passwd command |awk 'pattern {action}' 示例:df -P | grep '/' |awk '$4 > 25000 {print $4}'

    字段分割及相关变量

    $1,$2,$3...$n:awk中用该顺序形式表示files中每行以间隔符号分割的各列的不同字段
    $0             表示文本本身
    NF             表示当前记录的字段数(列数)
    $NF            最后一列
    $(NF-1)        倒数第二列
    FNR/NR         行号
    FILENAME       文件名
    "	"           制表符
    RS             换行符
    ""             打印字符串
    FS             定义间隔符
    ~              匹配,与==相比不是精确比较
    !~             不匹配,不精确比较
    ==             等于,必须全部相等,精确比较
    /[0-9][0-9]+/  两个或两个以上数字
    -F'[:#/]'      定义三个分隔符
    # awk -F: '{print $0}' /etc/passwd        //打印文件所有内容
    # awk -F: '{print NR, $0}' /etc/passwd /etc/hosts    //打印文件所有内容,并包括行号
    # awk -F: '{print FNR,$0}' /etc/passwd /etc/hosts
    # awk -F: '{print $0,NF}' /etc/passwd    //保留记录的字段数
    # awk 'BEGIN{FS=":"}{print $1,$3}' /etc/passwd    //输入字段分隔符,默认为空格

    格式化输出:

    print函数
    # date |awk '{print "Month: "$2 "
    Year: "$NF}'
    # awk -F: '{print "username is: " $1 "	 uid is: "$3}' /etc/passwd
    # awk -F: '{print "	username and uid: " $1,$3 "!"}' /etc/passwd
    # head -5 /etc/passwd|awk -F: 'BEGIN {print "user	homedir	shell"RS"***********************"};{print $1"	"$(NF-1)"	"$NF};END {print"************END************"}
    print函数
    # date |awk '{print "Month: "$2 "
    Year: "$NF}'
    # awk -F: '{print "username is: " $1 "	 uid is: "$3}' /etc/passwd
    # awk -F: '{print "	username and uid: " $1,$3 "!"}' /etc/passwd
    参数说明:
        %s 字符类型
        %d 数值类型
        占15字符
        - 表示左对齐,默认是右对齐
        printf默认不会在行尾自动换行,加
    

    awk模式和动作

      任何awk语句都由模式和动作组成。模式部分决定动作语句何时触发及触发事件。处理即对数据进行的操作。如果省略模式部分,动作将时刻保持执行状态。模式可以是任何条件语句或复合语句或正则表达式。模式包括两个特殊字段 BEGIN和END。使用BEGIN语句设置计数和打印头。BEGIN语句使用在任何文本浏览动作之前,之后文本浏览动作依据输入文本开始执行。END语句用来在awk完成文本浏览动作后打印输出文本总数和结尾状态。

    模式可以是:正则表达式、比较表达式、条件表达式、算术运算符、逻辑操作符和复合模式、范围模式等。

    正则表达式:

    匹配记录(整行):
    # awk '/^alice/'  /etc/passwd
    # awk '!/root/' passwd
    
    匹配字段:匹配操作符(~ !~)
    # awk -F: '$1 ~ /^admin/'  /etc/passwd
    # awk -F: '$NF !~ /nologin$/'  /etc/passwd

    比较表达式:

      比较表达式采用对文本进行比较,只有当条件为真,才执行指定的动作。比较表达式使用关系运算符,用于比较数字与字符串。

    运算符            含义                            示例
    <                小于                            x<y
    <=               小于或等于                       x<=y
    ==               等于                            x==y
    !=               不等于                          x!=y
    >=               大于等于                        x>=y
    >                大于                            x>y
    # awk -F: '$3 == 0' /etc/passwd
    # awk -F: '$3 < 10' /etc/passwd
    # awk -F: '$7 == "/bin/bash"' /etc/passwd
    # awk -F: '$1 == "root" ' /etc/passwd
    # awk -F: '$1 ~ /admin/ ' /etc/passwd
    # df -P | grep  '/' |awk '$4 > 25000'

    条件表达式:

    # awk -F: '$3>300 {print $0}' /etc/passwd
    # awk -F: '{ if($3>300) print $0 }' /etc/passwd
    # awk -F: '{ if($3>300) {print $0} }' /etc/passwd
    # awk -F: '{ if($3>300) {print $3} else{print $1} }' /etc/passwd

    算术运算:+ - * / %(模) ^(幂2^3)

    可以在模式中执行计算,awk都将按浮点数方式执行算术运算
    # awk -F: '$3 * 10 > 500' /etc/passwd

    逻辑操作符和复合模式:

    &&        逻辑与        a&&b
    ||        逻辑或        a||b
    !         逻辑非        !a
    # awk -F: '$3 > 50 && $3 <=100' /etc/passwd
    # awk -F: '$3 == 0 || $3 <=10' /etc/passwd
    # awk -F: '!($3 == 0 || $3 <=10)' /etc/passwd

    awk 脚本编程

    条件判断:

    if语句:

    //格式
    {if(表达式){语句;语句;...}}
    
    # awk -F: '{if($3==0) {print $1 " is administrator."}}' /etc/passwd
    
    # awk -F: '{if($3>0 && $3<1000){count++;}}  END{print count}' /etc/passwd    //统计系统用户数

    if...else语句:

    //格式
    {if(表达式){语句;语句;...}else{语句;语句;...}}
    
    # awk -F: '{if($3==0){print $1} else {print $7}}' /etc/passwd
    
    # awk -F: '{if($3==0){count++} else{i++}} END{print "管理员个数: "count ; print "系统用户数: "i}' /etc/passwd

    if...else if...else语句:

    //格式
    {if(表达式1){语句;语句;...}else if(表达式2){语句;语句;...}else if(表达式3){语句;语句;...}else{语句;语句;...}}
    
    # awk -F: '{if($3==0){i++} else if($3>999){k++} else{j++}} END{print i; print k; print j}' /etc/passwd
    
    # awk -F: '{if($3==0){i++} else if($3>999){k++} else{j++}} END{print "管理员个数: "i; print " 普通用个数: "k; print "系统用户: "j}' /etc/passwd

    循环:

    while:

    # awk 'BEGIN{i=1; while(i<=10){print i; i++}  }'
    # awk -F: '{i=1; while(i<=10) {print $0;  i++}}' /etc/passwd        //将每行打印10次

    for:

    # awk 'BEGIN{for(i=1;i<=5;i++){print i} }'                          //C风格for
    
    awk -F: '{for(i=1;i<=10;i++) print $0}' /etc/passwd                 //将每行打印10次

    数组:

    # awk -F: '{username[++i]=$1} END{print username[1]}' /etc/passwd
    root
    
    # awk -F: '{username[i++]=$1} END{print username[1]}' /etc/passwd 
    bin
    
    # awk -F: '{username[i++]=$1} END{print username[0]}' /etc/passwd 
    root

    数组遍历:

    # awk -F: '{username[x++]=$1} END{for(i=0;i<x;i++) print i,username[i]}' /etc/passwd
    
    # awk -F: '{username[++x]=$1} END{for(i=1;i<=x;i++) print i,username[i]}' /etc/passwd
    
    # awk -F: '{username[x++]=$1} END{for(i in username) {print i,username[i]} }' /etc/passwd
    
    # awk -F: '{username[++x]=$1} END{for(i in username) {print i,username[i]} }' /etc/passwd

     练习

    1. 统计/etc/passwd 中各种类型shell的数量
    # awk -F: '{shells[$NF]++}END{ for(i in shells){print i,shells[i]}}' /etc/passwd
    
    2. 网站访问状态统计 <当前时实状态 netstat>
    # netstat -ant |grep :80 |awk '{access_stat[$NF]++}END{for(i in access_stat){print i, access_stat[i]}}'
    # netstat -ant |grep :80 |awk '{access_stat[$NF]++} END{for(i in access_stat ){print i,access_stat[i]}}' |sort -k2 -n |head
    # ss -an |grep :80 |awk '{access_stat[$1]++} END{for(i in access_stat){print i,access_stat[i]}}'
    # ss -an |grep :80 |awk '{access_stat[$1]++} END{for(i in access_stat){print i,access_stat[i]}}' |sort -k2 -rn
    
    3. 统计当前访问的每个IP的数量 <当前时实状态 netstat,ss>
    # ss -an |grep :80 |awk -F":" '!/LISTEN/{ip_count[$(NF-1)]++} END{for(i in ip_count){print i,ip_count[i]}}' |sort -k2 -rn
    
    4. 统计Apache/Nginx日志中某一天的PV量  <统计日志>
    # grep '07/Aug/2012' access.log |wc -l
    
    5. 统计Apache/Nginx日志中某一天不同IP的访问量 <统计日志>
    # grep '07/Dec/2018' access.log |awk '{ips[$1]++} END{for(i in ips){print i,ips[i]} }' |sort -k2 -rn
    # grep '07/Dec/2018' access.log |awk '{ips[$1]++} END{for(i in ips){print i,ips[i]} }' |awk '$2>100' |sort -k2
    
    6. awk函数 统计用户名为4个字符的用户
    # awk -F: '$1~/^....$/{count++; print $1} END{print "count is: " count}' /etc/passwd
    # awk -F: 'length($1)==4{count++; print $1} END{print "count is: "count}' /etc/passwd
    
    7. 取得网卡IP(除ipv6以外的所有IP)
    # ifconfig |awk '/[ ]inet[ ]/{print $2}'
    
    8. 获得内存使用情况
    # free -m |awk 'NR==2{print $3*100/$2}'
    
    9. 获得磁盘使用情况
    # df |awk '//$/{print $5}'
    
    10. 清空本机的ARP缓存
    # arp |awk '!/Address/{print "arp -d " $1}'|bash
    # arp -n |awk '/^[0-9]/{print $1}' |xargs -I {} arp -d {}
  • 相关阅读:
    IIS无法加载字体文件(*.woff,*.svg)的解决办法
    windows server 2012 r2 安装IIS失败
    ASP.NET Core文件上传、下载与删除
    VS2015打开特定项目就崩溃
    sql server优化思路
    Asp.net Core中使用Session
    ABP之动态WebAPI
    web.xml和@WebServlet
    同一个页面 andriod和ios设备上的按钮颜色不一致
    地址中如果含有"+",发给服务器时"+"变成了空格问题解析
  • 原文地址:https://www.cnblogs.com/yanjieli/p/10082219.html
Copyright © 2011-2022 走看看