• awk.md


    简介

    awk是一个强大的文本分析工具,相对于grep的查找,sed的行编辑,awk在其对数据分析并生成报告时,显得尤为强大。简单来说awk就是把文件逐行的读入,以空格为默认分隔符将每行切片,切开的部分再进行各种分析处理。
    awk其名称得自于它的创始人 Alfred Aho 、Peter Weinberger 和 Brian Kernighan 姓氏的首个字母。实际上 AWK 的确拥有自己的语言: AWK 程序设计语言 , 三位创建者已将它正式定义为“样式扫描和处理语言”。它允许您创建简短的程序,这些程序读取输入文件、为数据排序、处理数据、对输入执行计算以及生成报表,还有无数其他的功能。

    命令格式和选项

    格式

    # awk [options] 'script' file1 file2, ...
    # awk [options] 'PATTERN { action }' file1 file2, ...
    

    命令选项

    • -F fs or --field-separator fs:指定输入文件折分隔符,fs是一个字符串或者是一个正则表达式,如-F:。
    • -v var=value or --asign var=value:赋值一个用户定义变量。
    • -f scripfile or --file scriptfile:从脚本文件中读取awk命令。

    print输出

    使用格式

    print item1, item2, ...
    

    要点
    1.各项目之间使用逗号隔开,而输出时则以空白字符分隔;
    2.输出的item可以为字符串或数值、当前记录的字段(如$1)、变量或awk的表达式;数值会先转换为字符串,而后再输出;
    3.print命令后面的item可以省略,此时其功能相当于print $0, 因此,如果想输出空白行,则需要使用print "";
    举例

    # awk 'BEGIN{print "one line.
    two line."}'
    one line.
    two line.
    # awk -F : '{print $1"-->"$7}' /etc/passwd |head -1
    root-->/bin/bash
    # awk -F : '{print $1,$7}' /etc/passwd |head -1
    root /bin/bash
    

    awk内置变量

    记录变量

    • FS:读取文件本时,所使用字段分隔符,默认是任何空格;
    • RS:输入文本信息所使用的换行符,默认是一个换行符;
    • OFS:输出字段分隔符(默认值是一个空格)。
    • ORS:输出记录分隔符(默认值是一个换行符)。

    数据变量

    • NR:awk命令所处理的记录数;如果有多个文件,这个数目会把处理的多个文件中行统一计数;
    • NF:当前记录的field个数;
    • FNR:与NR不同的是,FNR用于记录正处理的行是当前这一文件中被总共处理的行数;
    • ARGV:数组,保存命令行本身这个字符串,如awk '{print $0}' a.txt b.txt这个命令中,ARGV[0]保存awk,ARGV[1]保存a.txt;
    • ARGC:awk命令的参数的个数;
    • FILENAME:awk命令所处理的文件的名称;
    • ENVIRON:当前shell环境变量及其值的关联数组;

    举例

    # awk -F : '{print $1,$NF}' /etc/passwd |head -1
    root /bin/bash
    # awk  'BEGIN {FS=":"} {print $1,$NF}' /etc/passwd |head -1
    root /bin/bash
    # awk 'BEGIN {FS=":";OFS="-->"} {print $1,$NF}' /etc/passwd |head -1
    root-->/bin/bash
    # awk 'BEGIN {RS=" "} {print $0}' /etc/passwd 
    # awk 'BEGIN {ORS="@@@"} {print $0}' /etc/passwd 
    # awk '{print NR,$0}' /etc/issue /etc/redhat-release 
    1 S
    2 Kernel 
     on an m
    3 
    4 CentOS Linux release 7.2.1511 (Core)
    # awk '{print FNR,$0}' /etc/issue /etc/redhat-release 
    1 S
    2 Kernel 
     on an m
    3 
    1 CentOS Linux release 7.2.1511 (Core)
    

    自定义变量

    gawk允许用户自定义自己的变量以便在程序代码中使用,变量名命名规则与大多数编程语言相同,只能使用字母、数字和下划线,且不能以数字开头。gawk变量名称区分字符大小写。

    脚本中

    在gawk中给变量赋值使用赋值语句进行,例如:

    # awk 'BEGIN{var="variable testing";print var}'
    

    命令行

    gawk命令也可以在“脚本”外为变量赋值,并在脚本中进行引用。例如,上述的例子还可以改写为:

    # awk -v var="variable testing" 'BEGIN{print var}'
    

    printf

    printf命令的使用格式:

    printf format, item1, item2, ...
    

    要点

    1.其与print命令的最大不同是,printf需要指定format;
    2.format用于指定后面的每个item的输出格式;
    3.printf语句不会自动打印换行符;

    format格式的指示符都以%开头,后跟一个字符;如下:

    • %c: 显示字符的ASCII码;
    • %d, %i:十进制整数;
    • %e, %E:科学计数法显示数值;
    • %f: 显示浮点数;
    • %g, %G: 以科学计数法的格式或浮点数的格式显示数值;
    • %s: 显示字符串;
    • %u: 无符号整数;
    • %%: 显示%自身;

    修饰符

    • N: 显示宽度;
    • -: 左对齐;
    • +:显示数值符号;

    举例

    # awk -F : '{printf "%-20s %s
    ",$1,$NF}' /etc/passwd |head -1
    root                 /bin/bash
    

    输出重定向

    格式

    print items > output-file
    print items >> output-file
    print items | command
    

    特殊文件描述符

    /dev/stdin:标准输入
    /dev/sdtout: 标准输出
    /dev/stderr: 错误输出
    /dev/fd/N: 某特定文件描述符,如/dev/stdin就相当于/dev/fd/0;
    

    操作符

    算术

    • -x: 负值
    • +x: 转换为数值;
    • x^y:
    • x**y: 次方
    • x*y: 乘法
    • x/y:除法
    • x+y:
    • x-y:
    • x%y:

    字符串操作符

    只有一个,而且不用写出来,用于实现字符串连接;

    赋值操作符

    • =
    • +=
    • -=
    • *=
    • /=
    • %=
    • ^=
    • **=
    • ++
    • --

    需要注意的是,如果某模式为=号,此时使用/=/可能会有语法错误,应以/[=]/替代;

    布尔值

    awk中,任何非0值或非空字符串都为真,反之就为假;

    比较操作符

    • x < y True if x is less than y.
    • x <= y True if x is less than or equal to y.
    • x > y True if x is greater than y.
    • x >= y True if x is greater than or equal to y.
    • x == y True if x is equal to y.
    • x != y True if x is not equal to y.
    • x ~ y True if the string x matches the regexp denoted by y.
    • x !~ y True if the string x does not match the regexp denoted by y.
    • subscript in array True if the array array has an element with the subscript subscript.

    表达式间的逻辑关系符

    • &&
    • ||

    条件表达式

    • selector?if-true-exp:if-false-exp

    函数调用

    • function_name(para1,para2)

    常见的模式类型

    1.Regexp: 正则表达式,格式为/regular expression/
    2.expresssion: 表达式,其值非0或为非空字符时满足条件,如:$1 ~ /foo/ 或 $1 == "magedu",用运算符(匹配)和!(不匹配)。
    3.Ranges: 指定的匹配范围,格式为pat1,pat2
    4.BEGIN/END:特殊模式,仅在awk命令执行前运行一次或结束前运行一次
    5.Empty(空模式):匹配任意输入行;

    /正则表达式/:使用通配符的扩展集。
    关系表达式:可以用下面运算符表中的关系运算符进行操作,可以是字符串或数字的比较,如$2>%1选择第二个字段比第一个字段长的行。
    模式匹配表达式:
    模式,模式:指定一个行的范围。该语法不能包括BEGIN和END模式。
    BEGIN:让用户指定在第一条输入记录被处理之前所发生的动作,通常可在这里设置全局变量。
    END:让用户在最后一条输入记录被读取之后发生的动作。

    举例

    # awk -F : '$3==1000{print $0}' /etc/passwd
    fei:x:1000:1000::/home/fei:/bin/bash
    # awk -F : '$1~/^f/{print $0}' /etc/passwd
    ftp:x:14:50:FTP User:/var/ftp:/sbin/nologin
    fei:x:1000:1000::/home/fei:/bin/bash
    

    常见的Action

    1.Expressions
    2.Control statements:if, while等;
    3.Compound statements:组合语句;
    4.Input statements
    5.Output statements

    控制语句

    if-else

    语法

    if (condition) {then-body} else {[ else-body ]}
    

    举例

    # awk -F: '{if ($3==0) {print $1, "Adminitrator";} else { print $1,"Common User"}}' /etc/passwd
    # awk -F: '{if ($1 ~ /root/) {print $1,"is Administrator"}else {print $1,"is common"}}' /etc/passwd
    # awk -F: '{if ($1 == "root") {printf "%18s %s
    ",$1,"Admin"}else {printf "%18s %s
    ",$1,"common"}}' /etc/passwd
    # awk -F: -v sum=0 '{if ($3<1000) sum++}END{print sum}' /etc/passwd
    

    while

    语法

    while (condition){statement1; statment2; ...}
    

    举例

    # awk -F: '{i=1;while (i<=3) {print $i;i++}}' /etc/passwd
    # awk -F: '{i=1;while (i<=NF) { if (length($i)>=4) {print $i}; i++ }}' /etc/passwd
    

    do-while

    语法

    do {statement1, statement2, ...} while (condition)
    

    举例

    # awk -F: '{i=1;do {print $i;i++}while(i<=3)}' /etc/passwd
    # awk -F: '{i=4;do {print $i;i--}while(i>4)}' /etc/passwd
    

    for

    语法

    for ( variable assignment; condition; iteration process) { statement1, statement2, ...}
    

    举例

    # awk -F: '{for(i=1;i<=3;i++) print $i}' /etc/passwd
    # awk -F: '{for(i=1;i<=NF;i++) { if (length($i)>=4) {print $i}}}' /etc/passwd
    

    case

    语法

    switch (expression) { case VALUE or /REGEXP/: statement1, statement2,... default: statement1, ...}
    

    break 和 continue

    常用于循环或case语句中

    next

    提前结束对本行文本的处理,并接着处理下一行;例如,下面的命令将显示其ID号为奇数的用户:

    # awk -F: '{if($3%2==0) next;print $1,$3}' /etc/passwd
    

    awk中使用数组

    语法

    array[index-expression]
    

    index-expression可以使用任意字符串;需要注意的是,如果某数据组元素事先不存在,那么在引用其时,awk会自动创建此元素并初始化为空串;因此,要判断某数据组中是否存在某元素,需要使用index in array的方式。
    要遍历数组中的每一个元素,需要使用如下的特殊结构:

    for (var in array) { statement1, ... }
    

    其中,var用于引用数组下标,而不是元素值;
    举例

    # awk 'BEGIN{a["mon"]="Monday";a["sun"]="Sunday";print a["mon"]}'
    Monday
    # awk 'BEGIN{a["mon"]="Monday";a["sun"]="Sunday";print a["sun"]}'
    Sunday
    

    统计系统的用户默认shell出现次数:

    # awk -F: '{BASH[$NF]++}END{for (i in BASH){printf "%15s %d
    ",i,BASH[i]}}' /etc/passwd
          /bin/sync 1
          /bin/bash 2
      /sbin/nologin 18
         /sbin/halt 1
     /sbin/shutdown 1
    

    统计系统的网络连接状态的次数:

    netstat -tan|awk '/^tcp>/{state[$NF]++}END{for (a in state){printf "%15s %d
    ",a,state[a]}}'
    

    统计httpd日志中访问量前十的IP地址的访问次数:

     awk '{ip[$1]++}END{for (i in ip){printf "%18s %d
    ",i,ip[i]}}' access_20170119.log |sort -k2 -rn|head
    

    统计日志中各状态码的访问次数:

     awk '{ip[$9]++}END{for (i in ip){printf "%5s %d
    ",i,ip[i]}}' access_20170119.log |sort  -k2 -rn|head 
    

    统计每个用户的进程的占了多少内存(注:sum的RSS那一列):

    ps aux |awk 'NR!=1{user[$1]+=$6}END{for (i in user){print i,user[i]}}'
    polkitd 11804
    dbus 1868
    postfix 7804
    root 114984
    

    内置函数

    spilt

    用法

    split(string, array [, fieldsep [, seps ] ])
    

    功能:将string表示的字符串以fieldsep为分隔符进行分隔,并将分隔后的结果保存至array为名的数组中;数组下标为从1开始的序列;
    举例
    显示连接服务器中IP最多的10个:

    netstat -tan|awk '/:80>/{split($5,clients,":");IP[clients[4]]++}END{for (i in IP){printf "%20s %d
    ",i,IP[i]}}' |sort -k2 -rn |head
    

    显示系统中磁盘空间使用超过20%的分区:

    df -lh | awk '!/^File/{split($5,percent,"%");if(percent[1]>=20){print $1}}'
    

    统计当前系统上每个客户端IP的连接中处于TIME_WAIT的连接状态的个数:

     netstat -tan |awk '/TIME_WAIT/{split($5,clients,":");IP[clients[4]]++}END{for (i in IP){printf "%20s %d
    ",i,IP[i]}}' |sort -k2 -rn |head
    

    统计ps aux命令执行时,当前系统上各状态的进程的个数:

    ps aux |awk '!/^USER/{state[$8]++}END{for (i in state){printf "%10s %d
    ",i,state[i]}}' |sort -k2 -rn
    

    统计ps aux命令执行时,当前系统上各用户的进程的个数:

     ps aux |awk '!/^USER/{state[$1]++}END{for (i in state){printf "%10s %d
    ",i,state[i]}}' |sort -k2 -rn
    

    显示ps aux命令执行时,当前系统上其VSZ(虚拟内存集)大于10000的进程及其PID:

     ps aux|awk '!/^USER/{if ($5>10000) print $2,$5,$NF}'
    

    length

    length([string])
    

    功能:返回string字符串中字符的个数;

    substr

    substr(string, start [, length])
    

    功能:取string字符串中的子串,从start开始,取length个;start从1开始计数;

    system

    system(command)
    

    功能:执行系统command并将结果返回至awk命令

    扩展学习

    http://www.cnblogs.com/repository/archive/2011/05/13/2045927.html
    http://www.runoob.com/linux/linux-comm-awk.html
    http://www.cnblogs.com/ggjucheng/archive/2013/01/13/2858470.html
    http://coolshell.cn/articles/9070.html

  • 相关阅读:
    数据查询
    泰勒展开及其应用
    搜索排序算法
    因子分解机 FM
    偏差方差分解
    Softmax 损失-梯度计算
    目标检测网络之 Mask R-CNN
    目标检测网络之 R-FCN
    深度学习-conv卷积
    目标检测网络之 YOLOv3
  • 原文地址:https://www.cnblogs.com/cuchadanfan/p/6540544.html
Copyright © 2020-2023  润新知