• 【文本处理命令】之awk命令详解


    一、awk命令简介

      awk 是一种很棒的语言,它适合文本处理和报表生成,其语法较为常见,借鉴了某些语言的一些精华,如 语言等。在 linux 系统日常处理工作中,发挥很重要的作用,掌握了 awk将会使你的工作变的高大上。 awk 是三剑客的老大,利剑出鞘,必会不同凡响。

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

    二、使用方法

    2.1  格式

    awk '{pattern + action}' {filenames}
    awk [options] 'script' var=value file(s)
    awk [options] -f scriptfile var=value file(s)

      其中 pattern 表示 AWK 在数据中查找的内容,而 action 是在找到匹配内容时所执行的一系列命令。花括号({})不需要在程序中始终出现,但它们用于根据特定的模式对一系列指令进行分组。 pattern就是要表示的正则表达式,用斜杠括起来。

    2.2 常用命令选项

    • -F fs   fs 指定输入分隔符(可指定一个或多个),fs可以是字符串或正则表达式

    • -v var=value 赋值一个用户定义变量,将外部变量传递给awk

    • -f scriptfile 从脚本文件中读取awk命令

    2.3 awk的内置变量

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

     

    2.4 运算符 

    2.5 正则表达式

    三、案例

     我们以passwd文件来操作。操作之前先备份好,使用备份的passwd文件操作

    [root@VM_0_10_centos shellScript]# awk -F ":" '{print $1}' /tmp/passwd 
    root
    bin
    # 这里可以使用“,”将打印的多个条件分隔,打印的效果会自动有空格。如果使用的是$1 $2,里边是用空格,那打印出来的第一列和第3列会挨在一起
    [root@VM_0_10_centos shellScript]# awk -F ":" '{print $1,$3}' /tmp/passwd 
    root 0
    bin 1
    [root@VM_0_10_centos shellScript]# awk -F ":" '{print $1 $3}' /tmp/passwd 
    root0
    bin1
    或
    [root@VM_0_10_centos shellScript]# awk -F ":" '{print $1 " " $3}' /tmp/passwd 
    root 0
    bin 1
    # 使用制表符打印出信息
    [root@VM_0_10_centos shellScript]# awk -F ":" '{print "user:"$1 "	uid:"$3}' /tmp/passwd 
    user:root    uid:0
    user:bin    uid:1

    1)只查看passwd文件(100内)第20到第30行内容。(面试)

    [root@VM_0_10_centos shellScript]# awk '{if(NR>=20 && NR<=30) print $1}' /tmp/passwd 
    abrt:x:173:173::/etc/abrt:/sbin/nologin
    sshd:x:74:74:Privilege-separated
    postfix:x:89:89::/var/spool/postfix:/sbin/nologin
    chrony:x:997:995::/var/lib/chrony:/sbin/nologin
    tcpdump:x:72:72::/:/sbin/nologin
    syslog:x:996:994::/home/syslog:/bin/false
    mysql:x:27:27:MySQL
    nagcmd:x:603:1000::/home/nagcmd:/sbin/nologin
    nagios:x:604:1001::/home/nagios:/sbin/nologin
    apache:x:1000:1002::/home/apache:/bin/bash
    nginx:x:602:993:Nginx
    # 不加$1打印20-30行所有内容 [root@VM_0_10_centos shellScript]# awk
    '{if(NR>=20 && NR<=30) print}' /tmp/passwd abrt:x:173:173::/etc/abrt:/sbin/nologin sshd:x:74:74:Privilege-separated SSH:/var/empty/sshd:/sbin/nologin postfix:x:89:89::/var/spool/postfix:/sbin/nologin chrony:x:997:995::/var/lib/chrony:/sbin/nologin tcpdump:x:72:72::/:/sbin/nologin syslog:x:996:994::/home/syslog:/bin/false mysql:x:27:27:MySQL Server:/var/lib/mysql:/bin/false nagcmd:x:603:1000::/home/nagcmd:/sbin/nologin nagios:x:604:1001::/home/nagios:/sbin/nologin apache:x:1000:1002::/home/apache:/bin/bash nginx:x:602:993:Nginx web server:/var/lib/nginx:/sbin/nologin [root@VM_0_10_centos shellScript]# nl /tmp/passwd | awk '{if(NR>=20 && NR<=30) print}' 20 abrt:x:173:173::/etc/abrt:/sbin/nologin 21 sshd:x:74:74:Privilege-separated SSH:/var/empty/sshd:/sbin/nologin 22 postfix:x:89:89::/var/spool/postfix:/sbin/nologin 23 chrony:x:997:995::/var/lib/chrony:/sbin/nologin 24 tcpdump:x:72:72::/:/sbin/nologin 25 syslog:x:996:994::/home/syslog:/bin/false 26 mysql:x:27:27:MySQL Server:/var/lib/mysql:/bin/false 27 nagcmd:x:603:1000::/home/nagcmd:/sbin/nologin 28 nagios:x:604:1001::/home/nagios:/sbin/nologin 29 apache:x:1000:1002::/home/apache:/bin/bash 30 nginx:x:602:993:Nginx web server:/var/lib/nginx:/sbin/nologin

     2)已知text.txt文件内容,打印出Poe和33794712,并以 Poe 33794712格式显示

    [root@VM_0_10_centos shellScript]# cat test.txt 
    I am Poe,my qq is 33794712
    # 使用多个分隔符,先使用空格分割,然后对分割结果再使用","分割
    [root@VM_0_10_centos shellScript]# awk -F "[ ,]" '{print $3,$7}' test.txt Poe 33794712 或 [root@VM_0_10_centos shellScript]# awk -F '[ ,]+' '{print $3,$7}' test.txt Poe 33794712

    3)awk -F  指定分割字符

    # -F 相当于内置变量FS
    [root@VM_0_10_centos shellScript]# awk 'BEGIN{FS=","} {print $1,$2}' test.txt 2 this is a test 3 Are you like awk This's a test 10 There are orange apple

    4)通过-v 设置变量

    [root@VM_0_10_centos shellScript]# cat test.txt 
    I am Poe,my qq is 33794712
    2
    7
    [root@VM_0_10_centos shellScript]# awk -vx=12 '{print $1,$1+x}' test.txt 
    I 12
    2 14
    7 19
    [root@VM_0_10_centos shellScript]# awk -vx=12 '{print $1,$(1+x)}' test.txt 
    I 
    2 
    7
    [root@VM_0_10_centos shellScript]# awk -vx=12 -vy=i '{print $1,$1+x,$1y}' test.txt 
    I 12 Ii
    2 14 2i
    7 19 7i

    5)格式化输出

    # 8s代表8个space  
    回车换行  %- 后面的-表示前面不空格,不加的话前面也会有8个空格
    # 因为这里是打印的$1和$4,所以前面格式输出的有两个值:%-8s和%-10s [root@VM_0_10_centos shellScript]# awk
    '{printf "%-8s %-10s ",$1,$4}' test.txt I qq 2 7

     6)过滤第一列大于2、等于2、第一列大于2且第2列等于'Are'

    [root@VM_0_10_centos shellScript]# awk '$1>2 {print $1,$3}' test.txt 
    3 you
    This's test
    10 are
    # 需注意,这里不能使用单=号,会被认为是赋值。判断是否等于要使用双等号==
    [root@VM_0_10_centos shellScript]# awk '$1==2 {print $1,$3}' test.txt 
    2 is
    [root@VM_0_10_centos shellScript]# awk '$1=2 {print $1,$3}' test.txt 
    2 is
    2 you
    2 test
    2 are
    [root@VM_0_10_centos shellScript]# awk '$1>2 && $2=="Are" {print $1,$3}' test.txt 
    3 you

    7)内置参数用法

    NF:字段数  NR:行号  FNR:文本行号(文件计数的行号)

    FS:记录是以什么为分隔符  RS:默认分隔符( )  FILENAME:当前文件名  

    OFS:输出记录分隔符(输出换行符),输出时用指定的符号代替换行符

    ORS:输出记录分隔符(默认值是一个换行符)

    [root@VM_0_10_centos shellScript]# cat test.txt 
    2 this is a test
    3 Are you like awk
    This's a test
    10 There are orange,apple,mongo
    [root@VM_0_10_centos shellScript]#  awk 'BEGIN{printf "%4s %4s %4s %4s %4s %4s %4s %4s %4s
    ","FILENAME","ARGC","FNR","FS",
    "NF","NR","OFS","ORS","RS";printf "---------------------------------------------
    "} {printf "%4s %4s %4s %4s %4s %4s %4s %4s %4s
    ",FILENAME,ARGC,FNR,FS,NF,NR,OFS,ORS,RS}'  test.txt 
    FILENAME ARGC FNR FS NF NR OFS ORS RS
    --------------------------------------------- test.txt 2 1 5 1 test.txt 2 2 5 2 test.txt 2 3 3 3 test.txt 2 4 4 4 [root@VM_0_10_centos shellScript]# awk -F "," 'BEGIN{printf "%4s %4s %4s %4s %4s %4s %4s %4s %4s ","FILENAME","ARGC","FNR" ,"FS","NF","NR","OFS","ORS","RS";printf "--------------------------------------------- "} {printf "%4s %4s %4s %4s %4s %4s %4s %4s %4s ",FILENAME,ARGC,FNR,FS,NF,NR,OFS,ORS,RS}' test.txt
    FILENAME ARGC FNR FS NF NR OFS ORS RS
    --------------------------------------------- test.txt 2 1 , 1 1 test.txt 2 2 , 1 2 test.txt 2 3 , 1 3 test.txt 2 4 , 3 4

    8)输出行号(行条数NR)及文件行号(FNR)

    # $0 在这里是打印文件所有内容
    [root@VM_0_10_centos shellScript]# awk '{print NR,FNR,$0}' test.txt 
    1 1 2 this is a test
    2 2 3 Are you like awk
    3 3 This's a test
    4 4 10 There are orange,apple,mongo

    9)输出指定的分隔符

    # 注意这里的$前后都加了空格,也可以不加空格,但是格式会比较紧凑
    [root@VM_0_10_centos shellScript]# awk '{print $1,$2,$5}' OFS=" $ " test.txt 
    2 $ this $ test
    3 $ Are $ awk
    This's $ a $ 
    10 $ There $ 

    10)使用正则,字符串匹配。匹配第2列包含“th”字符,并打印出第二列和第四列

    ~ 表示模式开始。// 中是模式。!~表示模式取反,不匹配搜索的行

    [root@VM_0_10_centos shellScript]# awk '$2 ~ /th/ {print $2,$4}' test.txt 
    this a

    四、awk脚本模式

      对于每个输入行, awk 都会执行每个脚本代码块一次。然而,在许多编程情况中,可能需要在 awk 开始处理输入文件中的文本之前执行初始化代码。对于这种情况, awk 允许您定义一个 BEGIN 块。

      因为 awk 在开始处理输入文件之前会执行 BEGIN 块,因此它是初始化 FS(字段分隔符)变量、打印页眉或初始化其它在程序中以后会引用的全局变量的极佳位置。
      awk 还提供了另一个特殊块,叫作 END 块。 awk 在处理了输入文件中的所有行之后执行这个块。通常, END 块用于执行最终计算或打印应该出现在输出流结尾的摘要信息。

    格式:

    • BEGIN{ 执行前的语句 }
    • END {处理完所有的行后要执行的语句 }
    • {处理每一行时要执行的语句}

    案例:

    1)通过脚本查看输出的效果

    [root@VM_0_10_centos shellScript]# cat score.txt 
    Marry   2143 78 84 77
    Jack    2321 66 78 45
    Tom     2122 48 77 71
    Mike    2537 87 97 95
    Bob     2415 40 57 62
    [root@VM_0_10_centos shellScript]# cat awk_score.awk 
    #/bin/awk -f
    # 注意上面使用的bash
    # 运行前,输出名称
    BEGIN {
        Chinese = 0
        Math = 0
        English = 0
    
        printf "NAME      NO.      Chinese      Math      English       TOTAL
    "
        printf "-------------------------------------------------------------
    "
    }
    # 运行中
    {
        Chinese += $3
        Math += $4
        English += $5
        printf "%-8s %-8s %6d %10d %10d %12d
    ",$1,$2,$3,$4,$5, $3+$4+$5
    }
    # 运行后
    END {
        printf "-------------------------------------------------------------
    "
        printf "  TOTAL:%16d %10d %10d 
    ",Chinese,Math,English
        printf "AVERAGE:%16.2f %10.2f %10.2f
    ",Chinese/NR,Math/NR,English/NR
    }
    [root@VM_0_10_centos shellScript]# awk  -f awk_score.awk score.txt 
    NAME      NO.      Chinese      Math      English       TOTAL
    -------------------------------------------------------------
    Marry    2143         78         84         77          239
    Jack     2321         66         78         45          189
    Tom      2122         48         77         71          196
    Mike     2537         87         97         95          279
    Bob      2415         40         57         62          159
    -------------------------------------------------------------
      TOTAL:             319        393        350 
    AVERAGE:           63.80      78.60      70.00

    2)计算文件大小

    [root@VM_0_10_centos shellScript]# ls -l *.sh
    -rwxr-xr-x 1 root root  675 Oct  8 14:36 addUser.sh
    -rwxr-xr-x 1 root root 1148 Oct 10 09:34 autoCreateUser.sh
    -rwxr-xr-x 1 root root  559 Oct  9 08:46 checkMem.sh
    -rwxr-xr-x 1 root root  338 Oct  9 08:58 checkRoot.sh
    -rwxr-xr-x 1 root root  574 Oct 10 10:28 createUsers.sh
    -rwxr-xr-x 1 root root  425 Oct 10 10:22 delUsers.sh
    -rwxr-xr-x 1 root root  628 Oct 14 09:16 modifyExtension.sh
    -rwxr-xr-x 1 root root  121 Oct 12 18:19 mulTable.sh
    -rwxr-xr-x 1 root root  844 Oct 10 10:56 numSort.sh
    -rwxr-xr-x 1 root root  518 Oct 12 17:41 progressBar2.sh
    -rwxr-xr-x 1 root root  784 Oct 12 16:38 progressBar.sh
    -rwxr-xr-x 1 root root  213 Oct 14 15:54 randowName.sh
    -rwxr-xr-x 1 root root  239 Oct 14 16:05 sum.sh
    -rwxr-xr-x 1 root root   33 Oct  8 14:50 test.sh
    [root@VM_0_10_centos shellScript]# ls -l *.sh | awk '{sum+=$5} END {print sum}'
    7099

    3)打印九九乘法表

    [root@VM_0_10_centos shellScript]# seq 9 | sed 'H;g' | awk -v RS='' '{for(i=1;i<=NF;i++)printf("%dx%d=%d%s", i, NR, i*NR, i
    ==NR?"
    ":"	")}'
    1x1=1 1x2=2 2x2=4 1x3=3 2x3=6 3x3=9 1x4=4 2x4=8 3x4=12 4x4=16 1x5=5 2x5=10 3x5=15 4x5=20 5x5=25 1x6=6 2x6=12 3x6=18 4x6=24 5x6=30 6x6=36 1x7=7 2x7=14 3x7=21 4x7=28 5x7=35 6x7=42 7x7=49 1x8=8 2x8=16 3x8=24 4x8=32 5x8=40 6x8=48 7x8=56 8x8=64 1x9=9 2x9=18 3x9=27 4x9=36 5x9=45 6x9=54 7x9=63 8x9=72 9x9=81

    4)统计passwd账户人数

    [root@VM_0_10_centos shellScript]# awk '{count++;} END{print "USER Total:" count}' /tmp/passwd 
    USER Total:35
    [root@VM_0_10_centos shellScript]# awk 'BEGIN {COUNT=0;print "[start]:" COUNT} {COUNT++;} END{print "USER Total:" COUNT }' 
    /tmp/passwd [start]:0
    USER Total:35
    [root@VM_0_10_centos shellScript]# awk 'BEGIN {COUNT=0;print "[start]:" COUNT} {COUNT+=1;} END{print "USER Total:" COUNT }'
     /tmp/passwd [start]:0
    USER Total:35

    5)查询某个文件字节大小

    [root@VM_0_10_centos shellScript]# ll users.txt | awk 'BEGIN {SIZE=0} {SIZE=$5+SIZE} END {print "[end] SIZE:" SIZE}'
    [end] SIZE:68
    或
    [root@VM_0_10_centos shellScript]# ll numSort.sh | awk 'BEGIN {SIZE=0} {SIZE=$5+SIZE} END {print "[end] SIZE:" SIZE/1024/10
    24 ,"M"}'[end] SIZE:0.000804901 M

    补充单位换算:

     6)经典:查看服务器的连接状态

    [root@VM_0_10_centos shellScript]# netstat -an|awk '/^tcp/ {++s[$NF]} END{for(a in s)print a,s[a]}'
    LISTEN 7
    ESTABLISHED 3
    TIME_WAIT 3

    7)查看日志访问情况

    awk '{a[$7]+=$10;++b[$7];total+=$10}END{for(x in a)print b[x],x,a[x]|"sort -rn -k1";print
    "total size is :"total}' /app/log/access_log
  • 相关阅读:
    Java 添加、验证PDF 数字签名
    Java 将PDF 转为Word、图片、SVG、XPS、Html、PDF/A
    Java 读取PDF中的文本和图片
    Java 将Word转为PDF、PNG、SVG、RTF、XPS、TXT、XML
    Java 添加、读取、删除PPT文档属性
    Java 添加、修改PPT幻灯片中的表格
    Java 转PPT为图片、PDF、SVG、XPS、ODP以及PPT和PPTX互转
    Java 添加Word脚注、尾注
    Java 添加Word目录的2种方法
    Java 添加Word页眉、页脚
  • 原文地址:https://www.cnblogs.com/HeiDi-BoKe/p/11693847.html
Copyright © 2020-2023  润新知