awk

1.Awk基础介绍

2.awk语法格式

第一种形式:awk 'BEGIN{} pattern {commands} END {}' file_name
第二种形式:standard output | awk BEGIN{} pattern {commands} END {}
第三种形式:awk [options] -f awk-script-file filenames

2.Awk工作原理

1.awk将文件中的每一行作为输入, 并将每一行赋给内部变量$0, 以换行符结束
2.awk开始进行字段分解,每个字段存储在已编号的变量中,从$1开始[默认空格分割]
3.awk默认字段分隔符是由内部FS变量来确定, 可以使用-F修订
4.awk行处理时使用了print函数打印分割后的字段
5.awk在打印后的字段加上空格,因为$1,$3 之间有一个逗号。逗号被映射至OFS内部变量中,称为输出字段分隔符, OFS默认为空格.
6.awk输出之后,将从文件中获取另一行,并将其存储在$0中,覆盖原来的内容,然后将新的字符串分隔成字段并进行处理。该过程将持续到所有行处理完毕.

3.Awk内部变量

$0      #将读入进来的一行数据存储至$0中,读入进来默认按行为分割由RS变量控制
$1      #经过FS变量字段分割后,将一行内容拆分成几段,分别赋值给$1 $2 $3.....
NF      #统计每一行由FS分割之后多少列,多少个字段
NR      #给每一行载入进来的内容,都添加一个编号
FS      #指定字段分隔符,默认空格为分割
RS      #指定读入进来的内容分隔符,默认按照 \n  换行符
OFS     #输出字段分割符,默认是空格为分割
ORS     #输出行分割符,默认是换行
print   #打印

4.Awk格式输出

  •   printf
    
    
    格式符   含义
    %s        打印字符串
    %d        打印十进制数
    %f        打印一个浮点数
    %x        打印十六进制数
    %o        打印八进制数
    
    修饰符   含义
    
    - 左对齐
    
    + 右对齐
[root@manager awk]# awk '
BEGIN { 
    printf "%-20s%-20s%-20s%-20s\n",
    "Name","shuxue","yuwen","yinx"
} 
{
    printf "%-20s%-20s%-20s%-20s\n",  $1,$2,$3,$4
}' file3.txt

Name                shuxue              yuwen               yinx                
Oldxu               20                  30                  40                  
oldqiang            10                  5                   2                   
oldguo              1                   1                   1                   
oldgao              1                   2                   3                   
oldboy              10                  2                   0  

5.Awk模式匹配

1.正则匹配
    2.运算符   <  >      +-/*
    3.与或非

符号  含义
<       小于
[root@chengyinwu ~/awk]# awk 'BEGIN{FS=":"}$3>50{print $0}' passwd
3、以:为分隔符,匹配/etc/passwd文件中第7个字段为/bin/bash的所有行信息
[root@chengyinwu ~/awk]# awk 'BEGIN{FS=":"}$7=="/bin/bash"{print $0}' passwd
[root@chengyinwu ~/awk]# awk 'BEGIN{FS=":"}$7 ~/\/bin\/bash/{print $0}' passwd

4、以:为分隔符,匹配/etc/passwd文件中第7个字段不为/bin/bash的所有行信息
[root@chengyinwu ~/awk]# awk 'BEGIN{FS=":"}$7!="/bin/bash"{print $0}' passwd
[root@chengyinwu ~/awk]# awk 'BEGIN{FS=":"}$7 !~/\/bin\/bash/{print $0}' passwd

5、以:为分隔符,匹配/etc/passwd文件中第3个字段包含3个数字以上的所有行信息
[root@chengyinwu ~/awk]# awk 'BEGIN{FS=":"}$3 ~ /[0-9]{3,}/{print $0}' passwd 
布尔运算符匹配示例
符号  含义
||      或
&&      与
!       非
1、以:为分隔符,匹配passwd文件中包含ftp或mail的所有行信息。
[root@chengyinwu ~/awk]# awk 'BEGIN{FS=":"}$1=="ftp"||$1=="mail"{print $0}' passwd

2、以:为分隔符,匹配passwd文件中第3个字段小于50并且第4个字段大于50的所有行信息。
[root@chengyinwu ~/awk]# awk 'BEGIN{FS=":"}$3<50 && $4>50{print $0}' passwd

3.匹配没有/sbin/nologin 的行。
[root@chengyinwu ~/awk]# awk 'BEGIN{FS=":"} $0 !~ /\/sbin\/nologin/{print $0}' passwd
[root@manager awk]# awk 'BEGIN{FS=":"} $7 != "/sbin/nologin"' passwd 

a

wk的 + - * / % 支持小数
    运算符 含义

    +       加

    -       减

            乘
      /     除
      %     余
[root@manager awk]# cat student.txt 
oldxu       80    90    96    98
oldqiang    93    98    92    91
oldguo      78    76    87    92
oldli       86    89    68    92

oldgao      85    95    75    90
本章练习示例:
1.找出/etc/passwd文件中uid为0的。
[root@chengyinwu ~/awk]# awk 'BEGIN{FS=":"}$3==0' passwd

2.找出/etc/passwd文件中uid小于10的。
[root@chengyinwu ~/awk]# awk 'BEGIN{FS=":"}$3<10' passwd

3.找出/etc/passwd文件中uid 小于50,且bash为/bin/bash 的行
    awk 'BEGIN{FS=":"} $3<50 && /\/bin\/bash$/' passwd
    awk 'BEGIN{FS=":"} $3<50 && $7 == "/bin/bash"' passwd


4.匹配用户名为root并且打印uid小于15的行
    awk 'BEGIN{FS=":"} $3<15 && $1=="root"' passwd

5.匹配用户名为root或uid大于5000
    awk 'BEGIN{FS=":"} $3>5000 || $1=="root"' passwd
    

6.匹配uid为3位及以上的行
    awk 'BEGIN{FS=":"} $3 ~ /[0-9]{3,}/' passwd

7.匹配到 /sbin/nologin 的行
    awk '$0 ~ /\/sbin\/nologin/' passwd
    awk 'BEGIN{FS=":"} $7 ~ "/sbin/nologin" passwd
    awk 'BEGIN{FS=":"} $7 == "/sbin/nologin" passwd

8.磁盘使用率大于多少35092400,则打印可用的值。
    df  |awk 'NR==2 { if ($4 < 35092400) {print $4} }

9.正则匹配nginx开头的行
    awk '!/^#|^$|^ +#/' /etc/nginx/nginx.conf

翻译如下语句含义:
示例1

awk '/west/' datafile       #从datafile文件中匹配west行

awk '/^nor/' datafile       #从datafile文件中匹配以nor开头的行

awk '$3 ~ /^nor/' datafile 

awk '/^(no|so)/' datafile 

awk '{print $3,$2}' datafile

awk '{print $3 $2}' datafile 

awk '{print $0}' datafile 

awk '{print "Number of fields: "NF}' datafile 

awk '/nor/{print $3,$2}' datafile

awk '/^[ns]/{print $1}' datafile 

awk '$5 ~ /\. [7-9]+/' datafile 

awk '$2 !~ /E/   {print $1,$2}' datafile

awk '$3 ~ /^job/{print $3 "is a nice boy."}' datafile

awk '$8 ~ /[0-9][0-9]$/{print $8}' datafile

awk '$4 ~ /Cn$/{print "The price is $" $8 "."}' datafile

awk '/gdx/{print $0}' datafile 

awk -F: '{print "Number of fields: "NF}' /etc/passwd 

awk -F"[ :]" '{print NF}' /etc/passwd 

awk示例2
[root@oldxu ~]# cat b.txt 
oldxu:is a:good boy!
[root@oldxu ~]# awk '{print NF}' b.txt
[root@oldxu ~]# awk -F ':' '{print NF}' b.txt
[root@oldxu ~]# awk -F"[ :]" '{print NF}' b.txt
[root@chengyinwu ~/awk]# awk -F "[ :]" '{print $1}' b.txt 
oldxu
[root@chengyinwu ~/awk]# awk -F "[ :]" '{print $2}' b.txt 
is
[root@chengyinwu ~/awk]# awk -F "[ :]" '{print $3}' b.txt 
a
[root@chengyinwu ~/awk]# awk -F "[ :]" '{print $4}' b.txt 
good
[root@chengyinwu ~/awk]# awk -F "[ :]" '{print $5}' b.txt 
boy!

6.Awk条件判断

if语句格式: { if(表达式){语句;语句;... } }


1.以:为分隔符,打印当前管理员用户名称
    awk 'BEGIN{FS=":"} { if($3==0) { print $1,"是管理员"} }' /etc/passwd

2.以:为分隔符,统计系统用户数量
    awk 'BEGIN{FS=":"}  { if($3<1000) { i++ }} END { print i,"系统用户" }' /etc/passwd

3.以:为分隔符,统计普通用户数量
    awk 'BEGIN{FS=":"} { if ($3>=1000) { i++ } } END { print i,"个普通用 户"} /etc/passwd

4.以:为分隔符,只打印/etc/passwd中第3个字段的数值在50-100范围内的行信息
    awk 'BEGIN{FS=":"} $3>=50 && $3<100 {print $0}' /etc/passwd

if…else 语句格式: {if(表达式){语句;语句;… }else{语句;语句;…}}
统计当前的超级管理员有几个   统计当前的普通用户有多少   统计当前的系统用户有多少个
[root@chengyinwu ~/awk]# awk 'BEGIN{FS=":"} {if($3==0) {print $1} else {print $7}}' passwd
[root@oldxu ~]# awk 'BEGIN {FS=":"} {if($3==0) {count++} else{i++} }' /etc/passwd
[root@chengyinwu ~/awk]# awk 'BEGIN{FS=":"} {if ($3==0) {count++} else {i++}} END {print "管理员个数:" count;print "系统用户数:"i}' passwd 
管理员个数:1
系统用户数:38

if…else if…else 语句格式: { if(表达式 1){语句;语句;… }else if(表达式 2){语句;语句;. … }else{语句;语句;… }}
1.使用awk if打印出当前/etc/passwd文件管理员有多少个,系统用户有多少个,普通用户有多少个

[root@manager awk]# cat user_total.awk 
BEGIN{
    FS=":";OFS="\n"
}

{ 
    if ($3==0) 
         { i++ } 
    else if ($3>=1 && $3<=999)
         { j++ }  
    else
         { k++ }  
} 
END { 
    print i "个超级管理员", 
    j "个系统用户" ,
     k "个普通用户"
}

1.打印/etc/passwd文件中UID小于50的、或者UID小雨50大于100、或者UID大于100的用户名以及UID。
UID<50    root    0
UID<50    bin    1
50100    systemd    192
UID>100    chrony    998

[root@chengyinwu /tmp/awk]# awk -f uid.awk passwd
[root@chengyinwu /tmp/awk]# cat uid.awk 
BEGIN {
    FS=":"
}
    {
    if ($3<50) 
    {
        printf "%-20s%-20s%-10d\n","UID<50",$1,$3
    }
    else if ($3>50 && $3<100) 
    {
        printf "%-20s%-20s%-10d\n","50100) 
    {
        printf "%-20s%-20s%-10d\n","UID>100",$1,$3
    }
}

2.计算下列每个同学的平均分数,并且只打印平均分数大于90的同学姓名和分数信息
[root@oldxu ~]# cat student.txt
oldxu       80    90    96    98
oldqiang    93    98    92    91
oldguo      78    76    87    92
oldli       86    89    68    92
oldgao      85    95    75    90

[root@chengyinwu /tmp/awk]# awk -f student.awk student.txt
[root@chengyinwu /tmp/awk]# cat student.awk 
BEGIN{
    printf "%-10s%-10s%-10s%-10s%-10s%-10s%-10s\n",
    "Name","yuwen","shuxue","english","it","Total","AVG"
}

{
    total=$2+$3+$4+$5
    AVG=(total)/4
    if ( AVG > 90) {
    printf "%-10s%-10d%-10d%-10d%-10d%-10d%-10.2f\n",
    $1,$2,$3,$4,$5,total,AVG
    }
}

3.统计Nginx的状态,请分别打出200类 300类 400类 500类状态 出现了多少次
[root@manager awk]# awk -f log.awk access.log
[root@manager awk]# cat log.awk 
BEGIN {
    OFS="\n"
}
{
    if($9>=200 && $9<300)
    {i++}
    else if ($9>=300 && $9<400) {
    j++
    }
    else if ($9>=400 && $9<500) {
    k++
    }

    else if ($9>=500 && $9<600) {
    m++
    }

}
    END {
        print   "状态码:  次数", 
            "200类:"i"个",
            "300类:"j"个",
            "400类:"k"个",
            "500类:"m"个" }

awk实战
1:若内存剩余小于200M则输出“NO”
[root@manager awk]# free -m |awk 'BEGIN{NR==2} $4<300{print "NO"}'

2:若硬盘剩余大于20G则输出“yes”
[root@manager awk]# df -h |awk 'NR==6 { if ($4 > 20) {print "yes"}}'

3:打印access.log中下载文件大小超过5M的行


5:打印当前系统中uid大于1000的用户
[root@manager awk]# awk 'BEGIN{FS=":"} $3>1000{print $1}' passwd

6:显示当前系统中容量使用率大于5%的文件系统名称和挂载点
[root@manager awk]# df -h |awk '{if($5>5){print $1,$NF}}'

    cat /tmp/file1.txt
    Mike Harrington:[510] 548-1278:250:100:175
    Christian Dobbins:[408] 538-2358:155:90:201
    Susan Dalsass:[206] 654-6279:250:60:50
    Archie McNichol:[206] 548-1348:250:100:175
    Jody Savage:[206] 548-1278:15:188:150
    Guy Quigley:[916] 343-6410:250:100:175
    Dan Savage:[406] 298-7744:450:300:275
    Nancy McNeil:[206] 548-1278:250:80:75
    John Goldenrod:[916] 348-4278:250:100:175
    Chet Main:[510] 548-5258:50:95:135
    Tom Savage:[408] 926-3456:250:168:200
    Elizabeth Stachelin:[916] 440-1763:175:75:300

7:显示/tmp/file1.txt文件中所有电话号码
[root@manager awk]# awk 'BEGIN{FS="[: ]"} {print $4}' file1.txt

8:显示/tmp/file1.txt文件中Dan的电话号码
方法一:[root@manager awk]# awk -F "[: ]" '/Dan/ {print $4}' file1.txt
方法二:[root@manager awk]# awk 'BEGIN{FS="[: ]"}/Dan/{print $4}' file1.txt

9:显示/tmp/file1.txt文件中Susan的名字和电话号码
[root@manager awk]# awk -F "[ :]" '/Susan/ {print $1,$2,$4}' file1.txt

10:显示/tmp/file1.txt文件中所有区号为916的人名
[root@manager awk]# awk 'BEGIN{FS="[ :]"} /\[916\]/ {print $1,$2}' file1.txt

11:显示/tmp/file1.txt文件中所有头一个月捐款$250的人名
[root@manager awk]# awk 'BEGIN{FS="[ :]"} $5 ~ /250/ {print $1,$2}' file1.txt

12:显示/tmp/file1.txt文件中Savage的全名和电话号码
[root@manager awk]# awk 'BEGIN{FS="[ :]"} /Savage/ {print $1,$2,$4}' file1.txt

13:显示/tmp/file1.txt文件中只有四个字符的名
[root@manager awk]# awk '$1 ~/^[a-zA-Z]{4}$/' file1.txt

14:以空格文分隔符将/tmp/file1.txt文件中的第一列与最后一列调换位置
[root@manager awk]# awk 'BEGIN{FS=" "}{print $NF,$1}' file1.txt

15:使用awk取出IP地址
[root@manager awk]# ifconfig eth0 |awk 'NR==2{print $2}'

16:使用awk取出/etc/passwd第一列数据也就是取出用户名。
[root@manager awk]# awk 'BEGIN{FS=":"}{print $1}' passwd

你可能感兴趣的:(awk)