zoukankan      html  css  js  c++  java
  • awk、sed、grep三大shell文本处理工具之awk的应用

    awk

    1、是什么
    是一个编程语言。支持变量、数组、函数、流程控制(if...else/for/while)
    单行程序语言。

    2、工作流程
    读取file、标准输入、管道给的数据,从第一行开始读取,逐行读取,看是否匹配我们想要的数据(pattern模式匹配),对数据进行处理,直到读完所有的行,退出awk程序(执行的每一条awk的命令)

    3、语法
    awk [-F field seperator] 'pattern{action}' [file]

    -F: 指定元数据列(字段)分隔符
    ‘pattern’: 匹配模式
    作用:匹配出来要处理的数据。
    1)正则表达式
    [root@localhost html]# awk '/^J/{print}' awk_scores.txt

    2)关系表达式 > < >= <= == != ~ !~
    [root@localhost html]# awk '$2>90{print}' awk_scores.txt

    3) BEGIN模式 在awk程序执行后,但尚未执行处理动作前要做的工作(定义变量)
    [root@localhost html]# awk 'BEGIN{x="abc";print x}'

    4)END模式 awk程序执行完处理动作后要做的工作。(善后)
    [root@localhost html]# awk 'BEGIN{print "Scores report"} {print} END{print "Over!"}' awk_scores.txt

    {action}:处理动作,针对符合匹配模式的数据进行的处理动作
    如果没有pattern,只有action,会对所有的文本行执行action的处理动作
    如果没有action,只有pattern,会打印出符合匹配模式的行

    处理文本方式:
    [file]: awk要处理的文本行(源数据),可以是其他命令的输出、管道过来的数据

    4、指定awk的方式
    1)命令行方式:
    2)awk脚本:
    #!/usr/bin/awk -f
    BEGIN{
    print "Scores Report"
    }

    { print } //执行命令

    END{
    print "Over!"
    }

    [root@localhost html]# chmod u+x awk.awk
    [root@localhost html]# ./awk.awk awk_scores.txt

    3)文件
    BEGIN{
    print "Scores Report"
    }

    { print }

    END{
    print "Over!"
    }

    [root@localhost html]# awk -f awk.awk awk_scores.txt


    5、截取
    行 记录 Record
    列 字段 Field
    字符串 出现在行和列的交点上 确定哪一行的哪一列


    5.1 截取列
    awk 内置变量:$n n为数字 $1 $2 $3 表示第几列
    [root@localhost html]# awk '{print $1,$2}' awk_scores.txt

    awk 内置变量:$NF 最后一列
    [root@localhost html]# awk '{print $1,$NF}' awk_scores.txt
    [root@localhost html]# ifconfig eth0 | awk 'NR==2{print $2}'|awk -F: '{print $2}'

    5.2 截取行(行:NR)
    1)NR numbers of record FNR当前读到的行 NR==1 FNR==1 都是指第一行
    2)正则表达式
    3)条件表达式

    内置变量:$0 awk程序当前处理的行
    [root@localhost html]# awk 'NR==2{print $0}' awk_scores.txt

    示例:
    [root@localhost html]# awk '/^N/{print}' awk_scores.txt
    Nancy 89 90 73 82
    [root@localhost html]# awk 'NR==2{print}' awk_scores.txt
    Nancy 89 90 73 82
    [root@localhost html]# awk 'FNR==2{print}' awk_scores.txt
    Nancy 89 90 73 82
    [root@localhost html]# awk '$3>=90{print}' awk_scores.txt
    John 85 92 79 87
    Nancy 89 90 73 82

    5.3 截取字符串 哪一行的第几列找到字符串(列:$n)

    以下例子是截取第二行第5列的数据
    [root@localhost html]# df -h |awk 'NR==2{print $5}'
    49%

    6、格式化输出
    print 输出截取的数据,如果输出多列,列之间用“,”隔开-->输出后,变为空格
    改变输出后的列值分割符号:

    [root@localhost html]# awk '{print $3":"$4":"$1}' awk_scores.txt //冒号需要引起来
    92:79:John
    90:73:Nancy
    88:92:Tom
    65:83:Kity
    89:80:Han
    76:85:Kon

    7、BEGIN 

    BEGIN 其中的代码在执行动作之前执行,程序运行后,其中的代码只执行一次。设置定义变量。
    变量名 对应单词 意义

    列:
    FS      field separator 字段分隔符(awk处理的源文本的字段分隔符,默认空格或tab)
    OFS   output field separator 输出的分隔符(默认空格)

    行:
    RS      record separator 记录分隔符(默认换行符 )
    ORS   output record separator 输出记录换行符

    awk 'BEGIN{FS=":"}{print $1}' /etc/passwd //在读取源文件时,让awk认为列的分隔符为“:”
    awk 'BEGIN{FS=":"}{print $1,$2,$3}' /etc/passwd //输出多个列
    awk 'BEGIN{FS=":";OFS="-"}{print $1,$2,$3}' /etc/passwd //输出时,指定输出列的分隔符为“-”
    awk -F: '{print $1"-"$2"-"$3}' /etc/passwd(等同)

    [root@localhost html]# cat awk_scores.txt
    John 85 92 79 87
    Nancy 89 90 73 82

    Tom 81 88 92 81
    Kity 79 65 83 90
    Han 92 89 80 83
    Kon 88 76 85 97

    打印第一行:
    [root@localhost html]# awk 'BEGIN{RS=""}NR==1{print}' awk_scores.txt //通过“RS=""”定义行的分隔符为空行


    源文件:
    [root@localhost html]# cat awk_contacts.txt
    danny male 
    china beijing
    (8103)82456789

    jeck male
    Japan Tokyo
    (8103)82456789

    xi female
    America Washington
    (8103)82456789


    danny male china beijing (8103)82456789
    jeck male Japan Tokyo (8103)82456789
    xi female America Washington (8103)82456789

    要求输出时,每个用户占一行,仅输出用户名、性别、联系电话

    [root@localhost html]# awk 'BEGIN{RS="";FS=" "}{print $1,$3}' awk_contacts.txt
    danny male (8103)82456789
    jeck male (8103)82456789
    xi female (8103)82456789
    //解析:通过RS=""控制行的分隔符为空行,再通过FS=" "控制字段的分隔符为换行符(回车),然后打印第一列和第三列


    例:vim c.txt
    1
    2
    3
    4
    5

    计算出第一行和第三行的和
    [root@server ~]# awk 'BEGIN{RS="";FS=" "}{print $1+$3}' c.txt
    4

    //解析:通过RS=""控制行的分隔符为空行,通过RS之后上述例子只能分出一行(所有数字变成一行了),再通过FS=" "控制字段的分隔符为换行符(回车),然后打印第一列和第三列的和

    8、回头看awk的工作过程
    1)awk首选读取文件的第一行,将该行赋值给$0,默认行的分隔符是回车
    2)通过空格(制表符)将行分割成多个字段(列),并将列值赋值给$n,$1 $2 $3
    3) awk怎样直到列分隔符?运行程序之处,有一个内置变量FS来表示字段分隔符,程序初始化FS被定义为空格、制表符
    4)print 打印(执行处理动作),OFS默认为空格
    5)读取下一行

    9、高级玩法
    数学运算
    比较运算
    逻辑运算
    变量
    数组
    流程控制 if for while (类C)

    9.1 数学运算
    +  -  *  /  %   ^  **   注意:^号和**号都是指数运算
    [root@localhost html]# awk 'BEGIN{print 1+1}'
    2
    [root@localhost html]# awk 'BEGIN{print 1-1}'
    0
    [root@localhost html]# awk 'BEGIN{print 10*2}'
    20
    [root@localhost html]# awk 'BEGIN{print 10/2}'
    5
    [root@localhost html]# awk 'BEGIN{print 10%2}'
    0
    [root@localhost html]# awk 'BEGIN{print 10**2}'
    100
    [root@localhost html]# awk 'BEGIN{print 10**3}'
    1000
    [root@localhost html]# awk 'BEGIN{print 10^3}'
    1000
    [root@localhost html]# awk 'BEGIN{print 2^10}'

    [root@localhost html]# awk '{print $1,$2+$3+$4+$5}' awk_scores.txt
    John 343
    Nancy 334
    Tom 342
    Kity 317
    Han 344
    Kon 346


    9.2 比较运算
    >  <  >=  <=  ==  !=  ~  !~
    awk '$2!=89{print}' awk_scores.txt
    awk '/$1~^T/{print}' awk_scores.txt
    awk '$1~/^T/{print}' awk_scores.txt
    awk '$1~/^Han/{print}' awk_scores.txt

    awk '$2!=92{print}' awk_scores.txt
    awk '$2!~92{print}' awk_scores.txt

    注意:~号表示匹配正则表达式,!~表示不匹配。如上最后一例是表示 "截取第二列所有不为92的数据。"


    9.3 逻辑运算
    与 &&
    或 ||
    非 !

    [root@localhost html]# awk '$2>80 && $3>80 && $4>80 && $5>80{print}' awk_scores.txt


    9.4 变量
    awk 命名方式 shell key=value 不允许数字开头
    awk中变量如果没有没提前赋值,变量的初始值-->变量的类型(字符串和数值)
    字符串 -->初始值“空”
    数值 -->初始值“0”

    如果定义变量即引用变量:
    [root@localhost html]# awk 'BEGIN{n=1;print n}'
    1

    [root@localhost html]# awk 'BEGIN{var="abc";print var}'
    abc

    计算内存使用率:
    [root@localhost html]# awk 'NR==1{t=$2}NR==2{f=$2;print (t-f)/t*100}' /proc/meminfo | awk -F. '{print $1}'

    显示TCP进程连接状态及统计其数量:

    [root@localhost html]# netstat -n |awk '/^tcp.*/{++b[$NF]}END{for (i in b) print i,b[i]}'
    CLOSE_WAIT 2
    ESTABLISHED 18
    TIME_WAIT 277

    9.5 数组
    shell中
    array=(1 2 3 4 5) 数组的下标从0 引用echo ${array[*]}

    awk中
    array[n]=value 数组的下标从1开始

    awk引用数组:
    array[n] n表示下标

    定义数组array,赋值,引用:

    [root@localhost html]# awk 'BEGIN{array[1]=10;array[2]=11;array[3]=12;print array[1],array[2],array[3]}'
    10 11 12
    [root@localhost html]# vim array.awk
    [root@localhost html]# awk -f array.awk
    A B C
    [root@localhost html]# cat array.awk
    BEGIN{
    array[1]="A"
    array[2]="B"
    array[3]="C"

    print array[1],array[2],array[3]
    }
    [root@localhost html]# awk -f array.awk
    A B C


    9.6 if语句
    if (expression)
    {
    statement
    }
    else
    {
    statement
    }

    示例:

    #!/bin/awk -f --->#!/usr/bin/awk -f
    {
    if ($2>=80)
    { print $1,"Pass"}
    else
    { print $1,"Nopass"}
    }

    之判断为真的情况

    #!/bin/awk -f
    {
    if ($2>=80)
    { print $1,"Pass"}
    }


    [root@localhost html]# awk '{
    > if($2>=80)
    > {print $1,"Pass"}
    > }' awk_scores.txt
    John Pass
    Nancy Pass
    Tom Pass
    Han Pass
    Kon Pass

    9.7 for

    for循环为数组赋值

    #!/bin/awk -f
    BEGIN{
    for(i=1;i<5;i++)
    {
    array[i]=i
    print array[i]
    }
    }


    累加运算

    #!/bin/awk -f
    {
    sum=0
    for(i=1;i<5;i++)
    {
    sum+=$i
    }
    print sum
    }

    while

    格式:

    while(表达式)

    {语句}

    例:

    #!/bin/awk -f
    BEGIN{
    a=10;
    b=0;
    while (i<=10)
    {
    b=a+b;
    i++;
    }
    print b;
    }
  • 相关阅读:
    Android如何实现超级棒的沉浸式体验
    这次聊聊Promise对象
    svn add文件名包含@符号的解决方案
    证明3|n(n+1)(2n+1)
    Xcode迁移工程常见问题
    Multiple build commands for output file
    python中descriptor的应用
    xcode快捷键
    Cycript
    令assignment操作符返回一个reference to *this
  • 原文地址:https://www.cnblogs.com/dannylinux/p/8178205.html
Copyright © 2011-2022 走看看