• linux awk命令详解


    详细介绍AWK的文章,推荐去朱双印的个人博客,10分好评的个人博客,传送门

    本文章仅为个人精简参考使用,不适合初学者,详细的介绍文章,请用以上的传送门

    也可以稍微参考一下博客园:https://www.cnblogs.com/isykw/p/6258781.html

    也可以参考CSDN https://blog.csdn.net/sunchengquan/article/details/80276842

    本文包括

    • AWK简介
    • awk基本语法
    • awk常用命令选项
    • awk的几种模式
    • awk的内置变量
    • awk设置定义变量
    • awk模式的定义,空模式,关系运算模式,BEGIN模式,END模式,正则表达式模式
    • awk 在用 {x,y} 这种正则时,需要加参数
    • awk 支持if else, for ,while等控制语句
    • awk 计算日志中ip的数量
    • awk 把两个文件内的指定列,合并成一个文件
    • awk编程,善用FNR NR
    • awk数学运算
    • awk 生成随机数(利用awk的自带函数)
    • awk中使用shell的环境变量

    AWK简介

    awk是由Alfred Aho 、Peter Weinberger 和 Brian Kernighan这三个人创造的,awk由这个三个人的姓氏的首个字母组成。

    awk早期是在unix上实现的,所以,我们现在在linux的所使用的awk其实是gawk,也就是GNU awk,简称为gawk,awk还有一个版本,New awk,简称为nawk,但是linux中最常用的还是gawk。

    awk其实是一门编程语言,它支持条件判断、数组、循环等功能。所以,我们也可以把awk理解成一个脚本语言解释器。

    awk  更适合格式化文本,以文件的行为处理单位的,对文本进行较复杂格式处理

    AWK基础

    基本语法如下

    awk [options] 'Pattern{Action}' file
    awk '{ 
    
         BEGIN{stat1} 
         BEGIN{stat2} 
         pattern1{action1} 
         pattern2{action2} 
         ... 
         patternn{actionn} 
         {默认动作,无条件,始终执行} 
    
         END{stat1} 
         END{stat2} 
    }'

    常用命令选项

    -F 指定输入分隔符,fs可以是字符串或正则表达式,如 -F ':' , 默认的隔符是空格

    -v var=value -v是一种选项,var是一个变量的名称,value是一个变量的值,有很多内置的变量名称

    -v FS=':' 指定输入分隔符为: 和 -F 类似

    -v OFS='###' 指定 输出分隔符 ,默认输出分隔符为空格,可以换成任意的输出分割符
    -f scripfile 从脚本文件中读取awk命令

    awk命令插入一个文件,并使awk程序可执行,然后awk命令解释器作为脚本的首行,一遍通过键入脚本名称来调用。
    相当于shell脚本首行的:#!/bin/sh
    可以换成:#!/bin/awk

    如果只是显示/etc/passwd的账户
    #cat /etc/passwd |awk  -F ':'  '{print $1}'  
    root
    daemon
    bin
    sys

    AWK 包含两种特殊的模式:BEGIN 和 END。

    BEGIN 模式指定了处理文本之前需要执行的操作:

    END 模式指定了处理完所有行之后所需要执行的操作:

    以下实例展示了-v FS 指定输入分隔符 和 -v OFS 指定输出分隔符 指定BEGIN 和 END

    awk 处理 /etc/passwd  获取 $1,$7的数据

    而账户与shell之间以'++++'分割,

    而且在第一行添加文字 "name,shell",

    在最后一行添加"blue,/bin/nosh"。

    [root@cnblogs ~]# cat /etc/passwd |awk  -v FS=':' -v OFS="++++" 'BEGIN {print "name,shell"}  {print $1,$7} END {print "blue,/bin/nosh"}'
    name,shell
    root++++/bin/bash
    bin++++/sbin/nologin
    daemon++++/sbin/nologin
    ...
    ... blue,
    /bin/nosh

    awk内置变量

    awk有许多内置变量用来设置环境信息,这些变量可以被改变,下面给出了最常用的一些变量。

    ARGC               命令行参数个数
    ARGV               ARGV内置变量表示的是一个数组,这个数组中保存的是命令行所给定的参数。这样解释还是很模糊,不容易理解,我们来看看示例。
    ENVIRON            支持队列中系统环境变量的使用
    FILENAME           awk浏览的文件名
    FNR                各文件分别记录的行号
    FS                 FS: field separator设置输入域分隔符,等价于命令行 -F选项
    NF                 列数,number of the field,当前处理行的总列数(被分成几列)
    NR                 行数,number of the row,当前处理文本行的行号
    OFS                OFS:output field separator 输出字段分隔符, 默认为空白字符
    ORS                ORS:output row separator 输出记录分隔符(输出换行符),输出时用指定符号代替换行符
    RS                 RS:row separator 输入记录分隔符(输入换行符), 指定输入时的换行符

    除了内置变量,也可以定义自定义变量

    有两种定义方法

    方法一:-v varname=value  变量名区分字符大小写。

    方法二:在program中直接定义。

    [root@cnblogs ~]# awk -v myVAR="testVAR" 'BEGIN{print myVAR}'
    testVAR
    [root@cnblogs ~]# awk 'BEGIN{myVAR="testVAR";print myVAR}'
    testVAR

    也可以一次定义多个,如

    [root@cnblogs ~]# awk 'BEGIN{myVAR1="testVAR1";myVAR2="testVAR2";print myVAR1,myVAR2}'
    testVAR1 testVAR2

    统计/etc/passwd:文件名,每行的行号,每行的列数,对应的完整行内容:

    [root@cnblogs ~]#  awk  -F ':'  '{print "filename:" FILENAME ",linenumber:" NR ",columns:" NF ",linecontent:"$0}' /etc/passwd
    filename:/etc/passwd,linenumber:1,columns:7,linecontent:root:x:0:0:root:/root:/bin/bash
    filename:/etc/passwd,linenumber:2,columns:7,linecontent:bin:x:1:1:bin:/bin:/sbin/nologin
    filename:/etc/passwd,linenumber:3,columns:7,linecontent:daemon:x:2:2:daemon:/sbin:/sbin/nologin
    filename:/etc/passwd,linenumber:4,columns:7,linecontent:adm:x:3:4:adm:/var/adm:/sbin/nologin
    filename:/etc/passwd,linenumber:5,columns:7,linecontent:lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
    filename:/etc/passwd,linenumber:6,columns:7,linecontent:sync:x:5:0:sync:/sbin:/bin/sync
    filename:/etc/passwd,linenumber:7,columns:7,linecontent:shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown

    使用printf替代print,可以让代码更加简洁,易读

    [root@cnblogs ~]# awk  -F ':'  '{printf("filename:%10s,linenumber:%s,columns:%s,linecontent:%s
    ",FILENAME,NR,NF,$0)}' /etc/passwd
    filename:/etc/passwd,linenumber:1,columns:7,linecontent:root:x:0:0:root:/root:/bin/bash
    filename:/etc/passwd,linenumber:2,columns:7,linecontent:bin:x:1:1:bin:/bin:/sbin/nologin
    filename:/etc/passwd,linenumber:3,columns:7,linecontent:daemon:x:2:2:daemon:/sbin:/sbin/nologin
    filename:/etc/passwd,linenumber:4,columns:7,linecontent:adm:x:3:4:adm:/var/adm:/sbin/nologin
    filename:/etc/passwd,linenumber:5,columns:7,linecontent:lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
    filename:/etc/passwd,linenumber:6,columns:7,linecontent:sync:x:5:0:sync:/sbin:/bin/sync
    filename:/etc/passwd,linenumber:7,columns:7,linecontent:shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown

    AWK模式的概念就是条件

    "模式"这个词听上去文绉绉的,不是特别容易理解,那么我们换一种说法,我们把"模式"换成"条件",可能更容易理解,那么"条件"是什么意思呢?我们知道,awk是逐行处理文本的,也就是说,awk会先处理完当前行,再处理下一行,如果我们不指定任何"条件",awk会一行一行的处理文本中的每一行,如果我们指定了"条件",只有满足"条件"的行才会被处理,不满足"条件"的行就不会被处理。这样说是不是比刚才好理解一点了呢?这其实就是awk中的"模式"。

    再啰嗦一遍,当awk进行逐行处理的时候,会把pattern(模式)作为条件,判断将要被处理的行是否满足条件,是否能跟"模式"进行匹配,如果匹配,则处理,如果不匹配,则不进行处理。

    以下是AWK模式的示例 NF=2 或者 NF>2 是条件,也就是模式

    [root@cnblogs ~]# awk 'NF==2 {print $0}' /etc/passwd
    ftp:x:14:50:FTP User:/var/ftp:/sbin/nologin
    sshd:x:74:74:Privilege-separated SSH:/var/empty/sshd:/sbin/nologin
    nscd:x:28:28:NSCD Daemon:/:/sbin/nologin
    
    [root@cnblogs ~]# awk 'NF>2 {print $0}' /etc/passwd
    systemd-network:x:192:192:systemd Network Management:/:/sbin/nologin
    dbus:x:81:81:System message bus:/:/sbin/nologin
    polkitd:x:999:998:User for polkitd:/:/sbin/nologin
    

    AWK支持正则表达式匹配

    除此之外,还要注意以下两点

    1、当在awk命令中使用正则模式时,使用到的正则用法属于"扩展正则表达式"。

    2、当使用 {x,y} 这种次数匹配的正则表达式时,需要配合--posix选项或者--re-interval选项。

    awk的"模式(Pattern)",

    空模式 没有条件,每行都处理

    关系运算模式 根据条件,处理符合条件的行

    BEGIN 模式

    END 模式

    正则模式

    AWK支持"if...else if...else"这样的"控制语句"

     AWK支持for 循环,while  循环,continue,break,do ... while 循环

    详细请参考,朱双印的博客:http://www.zsythink.net/archives/2062

    #for循环语法格式1
    for(初始化; 布尔表达式; 更新) {
    //代码语句
    }
     
    #for循环语法格式2
    for(变量 in 数组) {
    //代码语句
    }
     
    #while循环语法
    while( 布尔表达式 ) {
    //代码语句
    }
     
    #do...while循环语法
    do {
    //代码语句
    }while(条件)

     

     

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

    示例:

    awk 'BEGIN{
    test=100;
    if(test>90){
    print "very good"
    }
    else if(test>60){
    print "good"
    }
    else{
    print "no pass"
    }
    }'
    
    very good

    自定义变量用; 分号结尾


    while语句
    示例:

    awk 'BEGIN{
    test=100;
    total=0;
    while(i<=test){
    total+=i;
    i++;
    }
    print total;
    }'
    5050


    上图中,我们使用了一个空模式,一个END模式。

    如下示例,计算人名出现的次数

    awk '{for (i=1;i<=NF;i++) {count[$i]++}} END{for(j in count){print j,count[j]}}' test4

     以下示例得到小于100的随机数,使用了rand() 和 srand(),int() 函数

    用srand()是因为,如果只使用rand(),第一次的数值不会变化,每次都是一样的随机数

    [root@jenkins ~]# awk 'BEGIN{srand();print rand()}'
    0.0698597
    [root@jenkins ~]# awk 'BEGIN{srand();print 100*rand()}'
    79.413
    [root@jenkins ~]# awk 'BEGIN{srand();print int(100*rand())}'
    73
    [root@jenkins ~]# 

    更多awk函数用法,请参考:

    http://www.zsythink.net/archives/2113

    https://www.cnblogs.com/isykw/p/6258781.html

    按照列合并两个文件

    [root@cnblogs ~]# cat a
    1 2
    1 2
    1 2
    1 2
    1 2
    [root@cnblogs ~]# cat b
    3 4
    3 4
    3 4
    3 4
    3 4
    [root@cnblogs ~]# awk '{if(FNR==NR) {d[FNR]=$0}} {if(FNR!=NR){print d[FNR],$0}}' a b
    1 2 3 4
    1 2 3 4
    1 2 3 4
    1 2 3 4
    1 2 3 4
    [root@cnblogs ~]# awk '{if(FNR==NR) {d[FNR]=$1}} {if(FNR!=NR){print d[FNR],$2}}' a b
    1 4
    1 4
    1 4
    1 4
    1 4
    [root@cnblogs ~]# awk 'FNR==NR {x[FNR]=$0} FNR!=NR{print x[FNR],$0}' a b
    1 2 3 4
    1 2 3 4
    1 2 3 4
    1 2 3 4
    1 2 3 4
    [root@cnblogs ~]# 

    a和b 有相同的列,把相同的列结合在一起

    [root@cnblogs ~]# cat a
    116 t1
    117 t2
    118 t3
    [root@cnblogs ~]# cat b
    116 1000
    117 1500
    118 800
    [root@cnblogs ~]#  awk 'NR==FNR{a[$1]=$2}NR!=FNR{print a[$1],$2}'  a b
    t1 1000
    t2 1500
    t3 800
    [root@cnblogs ~]# awk '{print NR ,FNR ,$1,$2}' a b
    1 1 116 t1
    2 2 117 t2
    3 3 118 t3
    4 1 116 1000
    5 2 117 1500
    6 3 118 800

     awk数学运算示例

    求1除以3结果保留一位小数,并且用%号表示数值

    [root@cnblogs ~]# t1=1
    [root@cnblogs ~]# t2=3
    [root@cnblogs ~]# awk 'BEGIN{printf "%.1f%
    ",("'$t1'"/"'$t2'")*100}'
    33.3%
    [root@cnblogs ~]# 

    awk中使用shell的环境变量

    第一种方法,使用-v ,定义变量可以引用变量

    [root@cnblogs ~]# abc=66666
    [root@cnblogs ~]# awk -v myVAR="$abc" 'BEGIN{print myVAR}'
    66666
    [root@cnblogs ~]# var="test"
    [root@cnblogs ~]# awk -v var="$var" 'BEGIN{print var}'
    test

     第二种方法,在awk中直接引用,使用字符串变量 ,

    注意使用前格式必须是先用单引号括住再用双引号括住,如:
    "
    '$var'"
    如果变量中含有空格或者特殊符号,需要如下
    "'"$var"'"

    如果不是用脚本文件方式执行,直接在shell里执行,需要先用export var=test 导出为环境变量,

    这样其后的awk子进程才会有该变量。

    [root@cnblogs ~]# var="test"
    [root@cnblogs ~]# awk 'BEGIN{print "'$var'"}'
    test
    [root@cnblogs ~]# var="this is a test"
    [root@cnblogs ~]# awk 'BEGIN{print "'"$var"'"}'
    this is a test
    [root@cnblogs ~]# 
    [root@cnblogs ~]# export var="this is a test"
    [root@cnblogs ~]# awk 'BEGIN{print "'"$var"'"}'
    this is a test
    [root@cnblogs ~]# 

    所有IP的连接数统计

    awk 'BEGIN{while("netstat -an"|getline){if( $5 ~ /[1-255]/){split($5,t1,":");tarr[t1[1]]++;}}for(k in tarr){print k,tarr[k] | "sort -r -n -k2";}};'
  • 相关阅读:
    [Angular 9] Built-in template syntax $any
    [Angular 9] Improved Dependency Injection with the new providedIn scopes 'any' and 'platform'
    [Angular 9 Unit testing] Stronger typing for dependency injection in tests
    [Angular] Preserve the current route’s query parameters when navigating with the Angular Router
    [Angular] Do relative routing inside component
    [Typescript] Make your optional fields required in TypeScript
    [Typescript] Exclude Properties from a Type in TypeScript
    [Javascript] Hide Properties from Showing Up in "for ... in" Loops in JavaScript
    [Debug] Set and remove DOM breakpoints
    【职业素养】4种让你显得没教养的做法
  • 原文地址:https://www.cnblogs.com/faberbeta/p/awk001.html
Copyright © 2020-2023  润新知