zoukankan      html  css  js  c++  java
  • 文本三剑客之三---awk命令用法

    awk命令

    awk是一种编程语言,用于在linux/unix下对文本和数据进行处理。数据可以来自标准输入(stdin)、一个或多个文件,或其它命令的输出。它支持用户自定义函数和动态正则表达式等先进功能,是linux/unix下的一个强大编程工具。它在命令行中使用,但更多是作为脚本来使用。awk有很多内建的功能,比如数组、函数等,这是它和C语言的相同之处,灵活性是awk最大的优势。

    awk命令格式和选项

    语法形式

    awk [options] 'script' var=value file(s)
    awk [options] -f scriptfile var=value file(s)

    常用命令选项

    -F fs   fs指定输入分隔符,fs可以是字符串或正则表达式,如-F:
    -v var=value   赋值一个用户定义变量,将外部变量传递给awk
    -f scripfile  从脚本文件中读取awk命令
    -m[fr] val   对val值设置内在限制,-mf选项限制分配给val的最大块数目;-mr选项限制记录的最大数目。这两个功能是Bell实验室版awk的扩展功能,在标准awk中不适用。

    awk模式和操作

    awk脚本是由模式和操作组成的。

    模式

    模式可以是以下任意一个:

    /正则表达式/:使用通配符的扩展集。
    关系表达式:使用运算符进行操作,可以是字符串或数字的比较测试。
    模式匹配表达式:用运算符~(匹配)和~!(不匹配)。
    BEGIN语句块、pattern语句块、END语句块:

    操作

    操作由一个或多个命令、函数、表达式组成,之间由换行符或分号隔开,并位于大括号内,主要部分是:

    awk脚本基本结构

    awk 'BEGIN{ print "start" } pattern{ commands } END{ print "end" }' file

    一个awk脚本通常由:BEGIN语句块、能够使用模式匹配的通用语句块、END语句块3部分组成,这三个部分是可选的。任意一个部分都可以不出现在脚本中,脚本通常是被单引号双引号中,例如:

    awk 'BEGIN{ i=0 } { i++ } END{ print i }' filename
    awk "BEGIN{ i=0 } { i++ } END{ print i }" filename

    awk的工作原理

    awk 'BEGIN{ commands } pattern{ commands } END{ commands }'
    • 第一步:执行BEGIN{ commands }语句块中的语句;
    • 第二步:从文件或标准输入(stdin)读取一行,然后执行pattern{ commands }语句块,它逐行扫描文件,从第一行到最后一行重复这个过程,直到文件全部被读取完毕。
    • 第三步:当读至输入流末尾时,执行END{ commands }语句块。

    BEGIN语句块在awk开始从输入流中读取行之前被执行,这是一个可选的语句块,比如变量初始化、打印输出表格的表头等语句通常可以写在BEGIN语句块中。

    END语句块在awk从输入流中读取完所有的行之后即被执行,比如打印所有行的分析结果这类信息汇总都是在END语句块中完成,它也是一个可选语句块。

    pattern语句块中的通用命令是最重要的部分,它也是可选的。如果没有提供pattern语句块,则默认执行{ print },即打印每一个读取到的行,awk读取的每一行都会执行该语句块。

    示例:

    [root@centos6~]#echo -e "A line 1
    A line 2" | awk 'BEGIN{ print "Start" } { print } END{ print "End" }'
    Start
    A line 1
    A line 2
    End

    当使用不带参数的print时,它就打印当前行,当print的参数是以逗号进行分隔时,打印时则以空格作为定界符。在awk的print语句块中双引号是被当作拼接符使用,例如:

    示例:

    [root@centos6~]#echo | awk '{ var1="v1"; var2="v2"; var3="v3"; print var1,var2,var3; }' 
    v1 v2 v3

    双引号拼接使用:

    [root@centos6~]#echo | awk '{ var1="v1"; var2="v2"; var3="v3"; print var1"="var2"="var3; }'
    v1=v2=v3

    { }类似一个循环体,会对文件中的每一行进行迭代,通常变量初始化语句(如:i=0)以及打印文件头部的语句放入BEGIN语句块中,将打印的结果等语句放在END语句块中。

    awk内置变量(预定义变量)

    说明:[A][N][P][G]表示第一个支持变量的工具,[A]=awk、[N]=nawk、[P]=POSIXawk、[G]=gawk

    $n 当前记录的第n个字段,比如n为1表示第一个字段,n为2表示第二个字段。 
    $0 这个变量包含执行过程中当前行的文本内容。
    [N] ARGC 命令行参数的数目。
    [G] ARGIND 命令行中当前文件的位置(从0开始算)。
    [N] ARGV 包含命令行参数的数组。
    [G] CONVFMT 数字转换格式(默认值为%.6g)。
    [P] ENVIRON 环境变量关联数组。
    [N] ERRNO 最后一个系统错误的描述。
    [G] FIELDWIDTHS 字段宽度列表(用空格键分隔)。
    [A] FILENAME 当前输入文件的名。
    [P] FNR 同NR,但相对于当前文件。
    [A] FS 字段分隔符(默认是任何空格)。
    [G] IGNORECASE 如果为真,则进行忽略大小写的匹配。
    [A] NF 表示字段数,在执行过程中对应于当前的字段数。
    [A] NR 表示记录数,在执行过程中对应于当前的行号。
    [A] OFMT 数字的输出格式(默认值是%.6g)。
    [A] OFS 输出字段分隔符(默认值是一个空格)。
    [A] ORS 输出记录分隔符(默认值是一个换行符)。
    [A] RS 记录分隔符(默认是一个换行符)。
    [N] RSTART 由match函数所匹配的字符串的第一个位置。
    [N] RLENGTH 由match函数所匹配的字符串的长度。
    [N] SUBSEP 数组下标分隔符(默认值是34)。 

    示例:

    df | awk '{print $1,$3}'      $1和$3之间默认有空白符隔开

    [root@centos7~]#df |awk '{print $1,$3}'
    Filesystem Used
    /dev/sda2 3909324
    devtmpfs 0
    tmpfs 0
    tmpfs 10168
    tmpfs 0
    /dev/sda3 32992
    /dev/sda1 166960
    tmpfs 0

    使用print $NF可以打印出一行中的最后一列字段,使用$(NF-1)则是打印倒数第二列字段,其他以此类推:

    示例一:

    [root@centos7~]#cat /etc/fstab
    
    #
    # /etc/fstab
    # Created by anaconda on Thu Aug 22 15:21:16 2019
    #
    # Accessible filesystems, by reference, are maintained under '/dev/disk'
    # See man pages fstab(5), findfs(8), mount(8) and/or blkid(8) for more info
    #
    UUID=38dd5f68-4f30-411c-b80a-0f4a60b06c6f / xfs defaults 0 0
    UUID=4357cc0e-6ee7-4a8f-8064-d1a54bdbf17f /boot xfs defaults 0 0
    UUID=eb4bf5e6-2645-4b1c-bda8-12c5831b81c2 /data xfs defaults 0 0
    UUID=b8c37e0b-3628-40b6-ac44-c36ca09b448f swap swap defaults 0 0
    
    [root@centos7~]#awk '/^UUID/{print $(NF-2)}' /etc/fstab
    defaults
    defaults
    defaults
    defaults

    示例二:

    [root@centos7~]#cat f1.txt
    aa dd cc
    ss dd cc
    aa cc nn
    
    [root@centos7~]#awk '{print $NF}' f1.txt
    cc
    cc
    nn

    统计文件中的行数:

    [root@centos7~]#df | awk '{print NR,$0}'     NR是显示每行的行号,$0显示所有行的内容
    
    1 Filesystem     1K-blocks    Used Available Use% Mounted on
    
    2 /dev/sda2      104806400 3909060 100897340   4% /
    
    3 devtmpfs          740204       0    740204   0% /dev
    
    4 tmpfs             756008       0    756008   0% /dev/shm
    
    5 tmpfs             756008   10168    745840   2% /run
    
    6 tmpfs             756008       0    756008   0% /sys/fs/cgroup
    
    7 /dev/sda3       52403200   32992  52370208   1% /data
    
    8 /dev/sda1        1038336  166960    871376  17% /boot
    
    9 tmpfs             151204       0    151204   0% /run/user/0

    示例三:

    df |awk 'END{ print NR }' 

    以上命令只使用了END语句块,在读入每一行的时,awk会将NR更新为对应的行号,当到达最后一行NR的值就是最后一行的行号,所以END语句块中的NR就是文件的行数。

    将外部变量值传递给awk

    借助-v选项,可以将外部值(并非来自stdin)传递给awk:

    [root@centos7~]#awk -v FS=":" '{print $1FS$3}'  /etc/passwd    给FS赋值:并以:作为分隔符显示第1和3列信息。
    
    root:0
    
    bin:1
    
    daemon:2
    
    adm:3
    
    lp:4
    
    sync:5

    shutdown:6

    另一种传递外部变量方法:可以调用shell中的变量格式显示

    [root@centos7~]#fs=:;awk -v FS=$fs '{print $1FS$3}' /etc/passwd
    
    root:0
    
    bin:1
    
    daemon:2
    
    adm:3
    
    lp:4
    
    sync:5
    
    shutdown:6

    取出IP地址示例:

    [root@centos7~]#df |awk -F"[[:space:]]+|%" '//dev/sd/{print $1,$(NF-2)}'    以空白符合%作为分隔符,可以直接取出第1列和倒数第3列的设备信息和利用率
    
    /dev/sda2 4
    
    /dev/sda3 1
    
    /dev/sda1 17
    
     
    
    [root@centos7~]#df |awk -F"[[:space:]]+|%" '//dev/sd/{print $1,$5}'      以空白符合%作为分隔符,可以直接取出第1列和倒第5列的设备信息和利用率
    
    /dev/sda2 4
    
    /dev/sda3 1
    
    /dev/sda1 17

    awk运算与判断

    作为一种程序设计语言所应具有的特点之一,awk支持多种运算,这些运算与C语言提供的基本相同。awk还提供了一系列内置的运算函数(如log、sqr、cos、sin等)和一些用于对字符串进行操作(运算)的函数(如length、substr等等)。这些函数的引用大大的提高了awk的运算功能。作为对条件转移指令的一部分,关系判断是每种程序设计语言都具备的功能,awk也不例外,awk中允许进行多种测试,作为样式匹配,还提供了模式匹配表达式~(匹配)和~!(不匹配)。作为对测试的一种扩充,awk也支持用逻辑运算符。

    算术运算符

    算术操作符:
    x+y, x-y, x*y, x/y, x^y, x%y
    - x:转换为负数
    +x:将字符串转换为数值
    字符串操作符:没有符号的操作符,字符串连接
    赋值操作符:
    =, +=, -=, *=, /=, %=, ^=,++, --
     下面两语句有何不同
    • awk ‘BEGIN{i=0;print ++i,i}’
    • awk ‘BEGIN{i=0;print i++,i}’
     
    特殊示例:
    a+=5;等价于:a=a+5
     

    操作符

    比较操作符:
    
    ==, !=, >, >=, <, <=
    
    模式匹配符:
    
    ~:左边是否和右边匹配,包含
    
    !~:是否不匹配

    示例:

    awk -F: '$0 ~ /root/{print $1}‘ /etc/passwd
    
    [root@centos7~]#awk '$0~"^root"' /etc/passwd    $0显示的行满足^root的正则表达式进行打印
    
    root:x:0:0:root:/root:/bin/bash
    
    [root@centos7~]#awk '$0!~"^root"' /etc/passwd    $0显示的行满足非以^root为行首的正则表达式进行打印
    
    [root@centos7~]#awk -F: '$3==0' /etc/passwd        第三列等于0的行进行打印
    
    root:x:0:0:root:/root:/bin/bash
    
    [root@centos7~]#lastb | awk '$3~/[[:digit:]]/{print $3}'    $3显示的行满足数字的正则表达进行打印第三列
    
    192.168.34.100
    
    192.168.34.1
    
    192.168.34.1
    
    192.168.34.1
    
    192.168.34.1
    [root@centos7~]#lastb  | awk '$3 ~  /^[[:digit:]]/{print $3}'  | sort | uniq -c |awk '$1  >=3{print  $1,$2}'    显示IP地址连接次数大于3的进行打印
    
    [root@centos7~]#awk -F: '($3>=1000){print $1,$3}' /etc/passwd            显示第三列大于1000的第1行和第3行。
    
    nfsnobody 65534
    
    liu 1000

    操作符

    逻辑操作符:与&&,或||,非!

    示例:

    [root@centos7~]#awk -F: '$3>=1000 && $3<=2000{print $1,$3}' /etc/passwd  显示第3列大于1000且小于2000的第1和第3列
    liu 1000
    [root@centos7~]#awk -F: '$3==0 || $3>=1000 {print $1,$3}' /etc/passwd   显示等于0和大于等于1000的第一和第三列
    root 0
    nfsnobody 65534
    liu 1000

    条件表达式(三目表达式)

    selector?if-true-expression:if-false-expression

    示例:

    [root@centos7~]#awk -F:  '{$3>=1000?name="common user":name="system user";print name,$1,$3}' /etc/passwd    $3大于1000的显示第一和第三列的name命名为common user,小于1000的,命名为system user
    system user root 0
    system user bin 1
    system user daemon 2
    system user adm 3 

    printf命令

    格式化输出:printf “FORMAT”, item1, item2, ...

    (1) 必须指定FORMAT

    (2) 不会自动换行,需要显式给出换行控制符,

    (3) FORMAT中需要分别为后面每个item指定格式符

    格式符:与item一一对应

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

      

    示例:

    [root@centos7~]#awk -F: '{printf "%-20s  %-10s
    ",$1,$3}' /etc/passwd     提取第1列和第3列将其进行左对齐
    root                  0            
    bin                   1         
    daemon           2         
    adm                 3         
    lp                     4         
    sync                5   

    awk PATTERN

    PATTERN:根据pattern条件,过滤匹配的行,再做处理

    (1)如果未指定:空模式,匹配每一行

    (2) /regular expression/:仅处理能够模式匹配到的行,需要用/ /括起来

    awk '/^UUID/{print $1}' /etc/fstab

    awk '!/^UUID/{print $1}' /etc/fstab

    (3) relational expression: 关系表达式,结果为“真”才会被处理

    真:结果为非0值,非空字符串

    假:结果为空字符串或0值

    (4)BEGIN/END模式

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

    END{}:仅在文本处理完成之后执行一次

    示例:

    [root@centos7~]#df | awk -F"[[:space:]]+|%"  '/^/dev/sd/{print $1,$5}'    以空白和%为界限,取出当前的IP地址和设备:
    
    /dev/sda2 4
    
    /dev/sda3 1
    
    /dev/sda1 17
    ss  -nt | awk -F"[[:space:]]+|:"  '/ESTAB/{print  $6}'   取第6列的IP
    
    ss  -nt | awk -F"[[:space:]]+|:"  '/ESTAB/{print  $(NF-2)}'  取倒数第三列的IP

     relational expression: 关系表达式,结果为“真”才会被处理

    真:结果为非0值,非空字符串

    假:结果为空字符串或0值

    赋值为0的示例:得出的结果是假

    [root@centos7~]# awk '0{print $0}' /etc/fstab   
    
    [root@centos7~]#echo $?
    
    0

    赋值为空的示例:得出的结果是假

    [root@centos7~]# awk '""{print $0}' /etc/fstab
    
    [root@centos7~]#echo $?
    
    0

    为非0时就会显示结果,就为真,示例如下:

    [root@centos7~]# awk '"1"{print $0}' /etc/fstab
    
    #
    
    # /etc/fstab
    
    # Created by anaconda on Thu Aug 22 15:21:16 2019
    
    #
    
    # Accessible filesystems, by reference, are maintained under '/dev/disk'
    
    # See man pages fstab(5), findfs(8), mount(8) and/or blkid(8) for more info
    
    #
    
    UUID=38dd5f68-4f30-411c-b80a-0f4a60b06c6f /                       xfs     defaults        0 0
    
    UUID=4357cc0e-6ee7-4a8f-8064-d1a54bdbf17f /boot                   xfs     defaults        0 0
    
    UUID=eb4bf5e6-2645-4b1c-bda8-12c5831b81c2 /data                   xfs     defaults        0 0
    
    UUID=b8c37e0b-3628-40b6-ac44-c36ca09b448f swap                    swap    defaults        0 0

    line ranges:行范围

    startline,endline:/pat1/,/pat2/ 不支持直接给出数字格式

    示例:

    [root@centos7~]#awk -F: '/^root/,/^adm/{print $1}' /etc/passwd  显示第1列root开头的行到adm开头的行
    
    root
    
    bin
    
    daemon
    
    adm
    [root@centos7~]#awk -F: '(NR>=10&&NR<=14){print NR,$1}' /etc/passwd  显示第10行到14行的第1列
    
    10 operator
    
    11 games
    
    12 ftp
    
    13 nobody
    
    14 systemd-netword

    特殊示例:

    打印奇数行:

    [root@centos7~]#seq  10 | awk  'i=!i'     第一个i为空值,为假,取反就会打印出1,第二个出来为1时,为真,取反为假,就不打印2,以此类推,得出以下结果。
    
    1
    
    3
    
    5
    
    7
    
    9

    打印偶数行:

    seq 10 | sed -n '1~2n'
    
    seq 10 | sed -n '2~2n'
    
    第一种情况:seq 10 | awk -v i="a" 'i=!i' 
    
    第二种情况:[root@centos7~]#seq  10 | awk  '!(i=!i)'
    
          2
    
          4
    
          6
    
          8  
    
          10

     常用的action分类

    • (1) Expressions:算术,比较表达式等

    • (2) Control statements:if, while等

    • (3) Compound statements:组合语句

    • (4) input statements

    • (5) output statements:print等

    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

    uexit

    awk控制语句if-else

    语法:if(condition){statement;…}[else statement]

    if(condition1){statement1}else if(condition2){statement2}else{statement3}

    使用场景:对awk取得的整行或某个字段做条件判断

    条件判断语句:if

    格式中语句1可以是多个语句,为了方便判断和阅读,最好将多个语句用{}括起来。awk分枝结构允许嵌套,其格式为:

    示例:

    awk 'BEGIN{
    test=100;
    if(test>90){
    print "very good";
    }
    else if(test>60){
    print "good";
    }
    else{
    print "no pass";
    }
    }'
    
    very good
    [root@centos7~]#awk 'BEGIN{score=60;if(score<60){print "no pass"}else if(score<=80){print "so so"}else{print "good"}}'       两种赋值变量方式都可以
    
    [root@centos7~]#awk -v score=60 'BEGIN{if(score<60){print "no pass"}else if(score<=80){print "so so"}else{print "good"}}' 两种赋值变量方式都可以
    
     so so
    
    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
    
    df -h|awk -F% '/^/dev/{print $1}'|awk '$NF>=80{print $1,$5}‘

    while循环

    语法:while(condition){statement;…}

    条件“真”,进入循环;条件“假”,退出循环

    使用场景:

    对一行内的多个字段逐一类似处理时使用

     对数组中的各元素逐一处理时使用

    示例:

    显示第一行,且统计第一行有多少个字节,并打印每个字符。

    [root@centos7~]#awk -F: 'NR==1{i=1;while(i<=NF){print $i,length($i);i++}}' /etc/passwd
    
    root 4
    
    x 1
    
    0 1
    
    0 1
    
    root 4
    
    /root 5

    示例:

    取出字符大于等于10的行,并统计字节数

    [root@centos7~]#awk '/^[[:space:]]*linux16/{i=1;while(i<=NF){if(length($i)>=10){print $i,length($i)};i++}}' /etc/grub2.cfg
    
    /vmlinuz-3.10.0-957.el7.x86_64 30
    
    root=UUID=38dd5f68-4f30-411c-b80a-0f4a60b06c6f 46
    
    LANG=en_US.UTF-8 16
    
    /vmlinuz-0-rescue-7a7fe51fce8c4639a5a046ac251485d0 50
    
    root=UUID=38dd5f68-4f30-411c-b80a-0f4a60b06c6f 46

    示例:生成随机1000个数字

    [root@centos7~]#for i in {1..1000};do if [ $i -eq 1 ];then echo -e "$RANDOMc" >> f1.txt;else  echo -e ",$RANDOMc" >> f1.txt;fi;done

    然后在随机数中取出最大值最小值:

    [root@centos7~]#awk -F ',' '{i=2;max=$1;min=$1;while (i<=NF){if($i > max){max=$i}else if($i <min){min=$i};i++}}END{print "max="max,"min="min}' f1.txt
    
    max=1653826510 min=8

    do-while循环

    语法:do {statement;…}while(condition)

    意义:无论真假,至少执行一次循环体

    示例:1+2..100求和

    [root@centos7~]#awk 'BEGIN{ total=0;i=0;do{ total+=i;i++;}while(i<=100);print total}'
    
    5050

    for循环

    语法:for(expr1;expr2;expr3) {statement;…}

    常见用法:

    for(variable assignment;condition;iteration process)

    {for-body}

    u特殊用法:能够遍历数组中的元素

    语法:for(var in array) {for-body}

     示例:

    [root@centos7~]#awk '/^[[:space:]]*linux16/{for(i=1;i<=NF;i++) {print $i,length($i)}}' /etc/grub2.cfg   显示当前行有多少个字符
    linux16 7
    /vmlinuz-3.10.0-957.el7.x86_64 30
    root=UUID=38dd5f68-4f30-411c-b80a-0f4a60b06c6f 46
    ro 2
    rhgb 4
    quiet 5
    LANG=en_US.UTF-8 16
    linux16 7
    /vmlinuz-0-rescue-7a7fe51fce8c4639a5a046ac251485d0 50
    root=UUID=38dd5f68-4f30-411c-b80a-0f4a60b06c6f 46
    ro 2
    rhgb 4
    quiet 5

    switch语句

    语法:switch(expression) {case VALUE1 or /REGEXP/: statement1; case

    VALUE2 or /REGEXP2/: statement2; ...; default: statementn}

    break和continue

    next:

    continue语句:当 continue 语句用于 while 或 for 语句时,使程序循环移动到下一个迭代。

    break语句:当 break 语句用于 while 或 for 语句时,导致退出程序循环。

    示例:

    awk 'BEGIN{total=0;for(i=1;i<=100;i++){if(i==50)break;total+=i};print total}'

    next语句:能能够导致读入下一个输入行,并返回到脚本的顶部。这可以避免对当前输入行执行其他的操作过程。

    示例:

    awk -F: '{if(NR%2==0)next;print NR,$0}'  /etc/passwd  显示的是奇数行
    
    awk -F: '{if(NR%2==0)print NR,$0}'  /etc/passwd    显示偶数行

    数组应用

    awk数组

    关联数组:array[index-expression]

    uindex-expression:

    • (1) 可使用任意字符串;字符串要使用双引号括起来

    • (2) 如果某数组元素事先不存在,在引用时,awk会自动创建此元素,并将其值

    初始化为“空串”  很重要,比较被遗忘的一个点

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

    数字做数组索引(下标):

    Array[1]="sun"

    Array[2]="kai"

    字符串做数组索引(下标):

    Array["first"]="www"

    Array["last"]="name"

    Array["birth"]="1987"

    使用中print Array[1]会打印出sun;使用print Array[2]会打印出kai;使用print Array["birth"]会得到1987。

    示例:

    [root@centos7~]#awk 'BEGIN{title["coo"]="wang";title["ceo"]="ma";print title["coo"]}'
    
    wang

    示例: 类似于去重的功能

    解释:line[$0]第一次显示的值为空值,然后取反就为真,打印第一个值,++会将第一次出现的值进行累加,然后取反为假,就不打印重复出现的值。

    [root@centos7~]#awk '{!line[$0]++;print $0,line[$0]}' f1.txt  显示当前的详细过程,验证第一次数组赋值为空值,取反为1.
    
    aaa 1
    
    sss 1
    
    aaa 2
    
    ccc 1
    
    ccc 2
    
    [root@centos7~]#awk '!line[$0]++' f1.txt
    
    aaa
    
    sss
    
    ccc
    
    [root@centos7~]#cat f1.txt
    
    aaa
    
    sss
    
    aaa
    
    ccc
    
    ccc

    数组for循环语句用法:

    若要遍历数组中的每个元素,要使用for循环

    for(var in array) {for-body}

    注意:var会遍历array的每个索引

    示例:

    [root@centos7~]#awk 'BEGIN{titel["coo"]="ma";titel["ceo"]="lige";titel[3]="liu";for(i in titel){print i,titel[i]}}'
    
    coo ma
    
    ceo lige
    
    3 liu

    示例: 统计ip的tcp类型的次数

    [root@centos7~]#netstat -tan | awk '/^tcp /{state[$NF]++}END{for(i in state){print i,state[i]}}'
    
    LISTEN 7
    
    ESTABLISHED 1

    示例:  提取连接态的IP和个数

    [root@centos7~]#ss -nt | awk -F"[[:space:]]+|:" '/ESTAB/{ip[$(NF-2)]++}END{for(i in ip){print i,ip[i]}}'
    
    192.168.34.1 1

    示例:  提取文件系统类型和计数

    [root@centos7~]#awk '/^UUID/{type[$3]++}END{for(i in type){print i type[i]}}' /etc/fstab
    
    swap1
    
    xfs3

    示例:分数求平均值

    [root@centos6~]#cat f1.txt
    name  sex      score
    a    f         90
    b    m    80
    c    f      50
    d    m    60
    
    [root@centos6~]#awk '!/^name/{sum[$2]+=$3;num[$2]++}END{for(i in num){print i,sum[i]/num[i]}}' f1.txt
    m 70
    f 70

    数值处理:

    rand():返回0和1之间一个随机数

    示例:随机生成四个数值,其中int是取整数,rand()默认取出的数值小数点两位,*100增大十倍

    [root@centos6~]#awk 'BEGIN{srand();for(i=1;i<=4;i++)print int(rand()*100)}'
    
    5
    
    12
    
    52
    
    84
    
    取出一位100以内的随机数:
    
    [root@centos7~]#awk 'BEGIN{srand();print int(rand()*100)}'
    
    56

    字符串处理:

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

    • sub(r,s,[t]):对t字符串搜索r表示模式匹配的内容,并将第一个匹配内容替换为s

    示例:将第一列的:替换为-

    [root@centos7~]#echo "2008:08:08 08:08:08" | awk 'sub(/:/,"-",$1)'
    
    2008-08:08 08:08:08

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

    示的内容

    示例:将整行:进行全部替换为-

    [root@centos7~]#echo "2008:08:08 08:08:08" | awk 'gsub(/:/,"-",$0)'
    
    2008-08-08 08-08-08

    示例:将第一列全部替换为-

    [root@centos7~]#echo "2008:08:08 08:08:08" | awk 'gsub(/:/,"-",$1)'
    
    2008-08-08 08:08:08

    • split(s,array,[r]):以r为分隔符,切割字符串s,并将切割后的结果保存至array所

    表示的数组中,第一个索引值为1,第二个索引值为2,…

    示例一:将整行以:形式进行分割,最后显示当前行字符和序列号,其中i显示序号,str[i]显示处理后的字符

     [root@centos7~]#echo "2008:08:08 08:08:08" | awk '{split($0,str,":")}END{for(i in str){print i,str[i]}}'
    
    4 08
    
    5 08
    
    1 2008
    
    2 08
    
    3 08 08

    示例二:整行以:为分割线,将第五列的ip地址取出并统计当前的次数

    [root@centos7~]#ss -nt | awk '/^ESTAB/{split($5,ip,":");count[ip[1]]++}END{for(i in count){print i,count[i]}}'
    
    192.168.34.1 1

    自定义函数格式:

    function name ( parameter, parameter, ... ) {
    
    statements
    
    return expression
    
    }

    示例:

    cat fun.awk
    
    function max(x,y) {
    
    x>y?var=x:var=y   如果x>y则var=x,否则var=y
    
    return var
    
    }
    
    BEGIN{a=3;b=2;print max(a,b)}
    
    awk -f fun.awk 

    system命令用法:

    空格是awk中的字符串连接符,如果system中需要使用awk中的变量可以使用

    空格分隔,或者说除了awk的变量外其他一律用""引用起来

    示例一:systeml  可以调用awk里边的命令变量

    [root@centos7~]#awk 'BEGIN{system("hostname")}'
    
    centos7.localdomain 

    示例二:

    [root@centos7~]#awk 'BEGIN{system("ls /boot")}'
    
    config-3.10.0-957.el7.x86_64 initramfs-3.10.0-957.el7.x86_64.img
    
    efi symvers-3.10.0-957.el7.x86_64.gz
    
    grub System.map-3.10.0-957.el7.x86_64
    
    grub2 vmlinuz-0-rescue-7a7fe51fce8c4639a5a046ac251485d0
    
    initramfs-0-rescue-7a7fe51fce8c4639a5a046ac251485d0.img  vmlinuz-3.10.0-957.el7.x86_64

    将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

    向awk脚本传递参数

    格式:

    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/passwd

    练习:将以下文件内容中FQDN取出域名并根据其进行计数从高到低排序

    http://mail.magedu.com/index.html

    http://www.magedu.com/test.html

    http://study.magedu.com/index.html

    http://blog.magedu.com/index.html

    http://www.magedu.com/images/logo.jpg

    http://blog.magedu.com/20080102.html

    答案:

    [root@centos7~]#cat f1.txt
    
    http://mail.magedu.com/index.html
    
    http://www.magedu.com/test.html
    
    http://study.magedu.com/index.html
    
    http://blog.magedu.com/index.html
    
    http://www.magedu.com/images/logo.jpg
    
    http://blog.magedu.com/20080102.html
    
    [root@centos7~]# awk -F"/" '{fqdn[$3]++}END{for(i in fqdn){print i,fqdn[i]}}' f1.txt | sort  -nr -k2
    
    www.magedu.com 2
    
    blog.magedu.com 2
    
    study.magedu.com 1
    
    mail.magedu.com 1
    

      

  • 相关阅读:
    使用postman做接口测试(三)
    使用postman做接口测试(二)
    使用postman做接口测试(一)
    RobotFramework安装扩展库包autoitlibrary(四)
    RobotFramework安装扩展库包Selenium2Library(三)
    记录.gitattributes 设置合并时使用本地文件无效的解决方案
    golang 踩坑日记
    linux常用命令记录
    vim配置文件
    mysql case when记录
  • 原文地址:https://www.cnblogs.com/struggle-1216/p/11699371.html
Copyright © 2011-2022 走看看