六、awk编程

本文详细介绍了awk编程,包括模式匹配、记录与域的概念、关系和布尔运算符、表达式、系统变量、格式化输出、内置字符串函数、向脚本传递参数以及条件语句和循环语句。awk语言适用于从文件或字符串中筛选和处理信息,其灵活性和强大的文本处理能力使其成为数据处理的有力工具。
摘要由CSDN通过智能技术生成

1.概述

  • awk语言可以从文件或字符串中基于指定规则浏览和抽取信息,在抽取信息的基础上,才能进行其他文本操作

  • awk程序有一个主输入循环(main input loop)维持,主输入循环反复执行,直到终止条件被触发

    主输入循环自动依次读取输入文件行,以供处理,而处理文件行的动作为用户定义

  • awk定义了连个特殊的字段:BEGIN和END

    • BEGIN用于在主输入循环之前执行,即在未读取输入文件行之前执行
    • END用于在主输入循环之后执行,即在读取输入文件行完毕后执行
  • awk编程模型分为三个阶段:

    1. 读输入文件之前的执行代码段(由BEGIN关键字标识)
    2. 读取输入文件时的执行代码段
    3. 读输入文件完毕之后的执行代码段(由END关键字标识)
  • awk调用方法

    1. 在shell命令行输入命令调用awk

      awk [-F域分隔符] 'awk程序段' 输入文件
    2. 将awk程序段插入脚本文件,然后通过awk命令调用它

      awk -f awk脚本文件 输入文件
    3. 将sed命令插入脚本文件后,设置该脚本文件为可执行,然后直接执行该脚本文件

2.awk编程

  • 任何awk语句都由模式(pattern)和动作(action)组成

    • 模式是一组用于测试输入行是否需要执行动作的规则

      模式决定动作何时触发和触发事件

    • 动作是包含语句、函数和表达式的执行过程

      动作执行对输入行的处理

2.1 awk模式匹配

awk '/^$/{print "This is a blank line."}' input_file
# 一旦匹配到空行,就执行打印操作
  • 单引号中间是awk程序段
  • ^$部分是模式
  • 花括号部分是动作
  • 模式和动作以/符号分隔

2.2 记录和域

  • awk将每个输入文件行定义为记录(Records)

  • 行中的每个字符串定义为域(Fields)

  • 域之间用空格、Tab键或其他符号进行分隔,分隔域的符号叫做分隔符

  • awk定义域操作符\(来指定执行动作的域,域操作符\)后面跟数字或变量来标识域的位置,每条记录的域从1开始编号,如$1表示第1个域,$2表示第2个域,$0表示所有的域

    awk '{print $2,$4,$1,$3,$0}' inputfile
    • 域操作符$后面还可以跟变量,或者变量运算表达式

      awk 'BEGIN {one=1;two=2} {print $(one+two)}' inputfile
      # 其中$(one+two)等价于$3
    • 用awk的-F选项可以改变分隔符

      awk -F"/t" '{print $3}' inputfile
      • 说明

        大写F选项用来改变分隔符,小写-f选项则表示调用awk脚本

  • 改变分隔符

    1. -F选项

    2. 使用awk环境变量FS,即通过在BEGIN字段中设置FS的值来改变分隔符

      awk 'BEGIN {FS="\t"} {print $0}' inputfile
      • 可以使用正则表达式将分隔符设置为多个字符

        FS="\t+"

2.3 关系和布尔运算符

  • awk定义了一组关系运算符用于awk模式匹配

    运算符意义
    <小于
    >大于
    <=小于等于
    >=大于等于
    ==等于
    !=不等于
    ~匹配正则表达式
    !~不匹配正则表达式
  • awk布尔运算符及其意义

    运算符意义
    ||逻辑或
    &&逻辑与
    逻辑非
  • 示例

    # 第1域匹配root
    awk 'BEGIN {FS=":"} $1~/root/' /etc/passwd 
    # 全部域匹配root
    awk 'BEGIN {FS=":"} $0~/root/' /etc/passwd
    # 全部域不匹配root
    awk 'BEGIN {FS=":"} $0!~/root/' /etc/passwd
    # 第3域值小于第4域值
    awk 'BEGIN {FS=":"} {if($3<$4) print $0}' /etc/passwd

2.4 表达式

​ awk表达式用于存储、操作和获取数据,一个awk表达式可由数值、字符常量、变量、操作符、函数和正则表达式自由组合而成。

  • 变量

    • 变量是一个值的标识符
    • 定义一个变量只需要定义一个变量名并将值赋给它即可
    • 变量名只能包含字母、数字和下划线,不能以数字开头
    • awk变量名区分大小写
    • 定义awk变量无须声明变量类型,每个变量有两种类型的值:字符串值和数值,awk根据表达式上下文来确定使用哪个值
    • 变量的默认值为0、默认字符串值为空
  • awk算术运算符及其意义

    运算符意义
    +
    -
    *
    /
    %
    ^或**乘方
    ++x在返回x值之前,x变量加1
    x++在返回x值之后,x变量加1

2.5 系统变量

  • 定义

    awk定义了很多内建变量用于设置环境信息,称为系统变量

    • 系统变量分类

      1. 用于改变awk的默认值,如域分隔符
      2. 用于定义系统值,在处理文本时可以读取这些系统值,如记录中的域数量、当前记录数、当前文件名等。
    • 说明

      awk动态改变第2种系统变量的值

  • awk环境变量及其意义

    变量名意义
    $n当前记录的第n个域,域间由FS分隔
    $0记录的所有域
    ARGC命令行参数的数量
    ARGIND命令行中当前文件的位置(以0开始标号)
    ARGV命令行参数的数组
    CONVFMT数字转换格式
    ENVIRON环境变量关联数组
    ERRNO最后一个系统错误的描述
    FIELDWIDTHS字段宽度列表,以空格键分隔
    FILENAME当前文件名
    FNR浏览文件的记录数
    FS字段分隔符,默认是空格键
    IGNORECASE布尔变量,如果为真,则进行忽略大小写的匹配
    NF当前记录中的域数量
    NR当前记录数
    OFMT数字的输出格式
    OFS输出域分隔符,默认是空格键
    ORS输出记录分隔符,默认是换行符
    RLENGTH由match函数所匹配的字符串长度
    RS记录分隔符,默认是空格键
    RSTART由match函数所匹配的字符串的第1个位置
    SUBSEP数组下标分隔符,默认值是\034

2.6 格式化输出

​ awk的一大主要功能是产生报表,报表要求按照预定的格式输出。

​ printf输出语句,可以规定输出的格式。

  • printf的基本语法

    printf (格式控制符,参数)
    • 格式控制符

      格式控制符,以%符号开始,用以描述格式规范

      格式控制符分为awk修饰符和格式符两种:

      • awk修饰符

        修饰符意义
        -左对齐
        width域的步长
        -prec小数点右边的位数
      • 格式符

        格式符意义
        %cASCII字符
        %d整数型
        %e浮点数,科学记数法
        %f浮点数
        %o八进制数
        %s字符串
        %x十六进制数
    • 参数列表

      与格式控制符相对应,是输出的对象

    • 示例

      # No.1 参数为列表形式
      awk 'BEGIN {FS=":"} {printf("%s\t%d\n",$1,$3)}' /etc/passwd
      
      # No.2 转换ASCII
      awk 'BEGIN {printf("%c\n",65)}'
      
      # No.3 
      # .prec表示输出小数点后的位数,浮点数长度控制在10位,2位小数点
      # 右对齐(printf的默认对其方式)
      awk 'BEGIN {printf("%10.2f\n",2020.1234)}'
      
      # No.4
      # printf修饰符-和width的用法
      #对第1个%s进行了修饰,-15表示该字符串长度控制为15位,并且左对齐,若字符串不足15位,则用空格补全
      awk 'BEGIN {FS=":"} {printf("%-15s\t%s\n",$1,$3)}' /etc/passwd
      
      # No.5
      # 要在输出的域顶部加上解释语言,可以在BEGIN字段中添加相应的输出注释
      awk 'BEGIN {FS=":";print "用户名\t\t用户编号"} {printf("%-15s\t%s\n",$1,$3)}' /etc/passwd
      
      # No.6
      # 单独使用.prec
      awk 'BEGIN {printf("%.3f\n",2021.0231)}'

2.7 内置字符串

​ awk内置的字符串函数,用于实现文本的字符串替换、查找以及分隔等功能。

  • awk字符串函数及其意义

    函数名意义
    gsub(r,s)在输入文件中用s替换r
    gsub(r,s,t)在t中用s替换r
    index(s,t)返回s中字符串第一个t的位置
    length(s)返回s的长度
    match(s,t)测试s是否包含匹配t的字符串
    split(r,s,t)在t上将r分成序列s
    sub(r,s,t)将t中第1次出现的r替换为s
    substr(r,s)返回字符串r中从s开始的后缀部分
    substr(r,s,t)返回字符串r中从s开始长度为t的后缀部分
  • 示例

    # No.1
    # 替换第1域上的root字符串
    awk 'BEGIN {FS=":";OFS=":"} gsub(/root/,"gridsphere",$1) {print $0}' /etc/passwd
    
    # No.2
    # 替换全部域上的root字符串
    awk 'BEGIN {FS=":";OFS=":"} gsub(/root/,'gridsphere') {print $0}'
    
    # No.3
    # index和length函数的用法
    awk 'BEGIN {print inex("gridsphere","ph")}'
    awk 'BEGIN {print length("gridsphere")}'
    
    # No.4
    # match(s,t)中,t可以是一个正则表达式,若匹配成功,返回匹配t的首位置;若不成功,则返回0
    # awk默认状态是区分大小写的,系统变量IGNORECASE设为1可忽略大小写
    awk 'BEGIN {print match("gridsphere",/D/)}'
    awk 'BEGIN {IGNORECASe=1;print match("gridsphere",/D/)}'
    
    # No.5
    # sub(r,s,t)只替换模式出现的第1个位置
    awk 'BEGIN {str="multiprocessor programming";sub(/pro/,"PRO",str);printf("%s\n",str)}'
    
    # No.6
    # substr返回字符串的指定后缀
    awk 'BEGIN {str="multiprocessor";print substr(str,6)}'
    awk 'BEGIN {str="multiprocessor";print substr(str,6,7)}'

2.8 向awk脚本传递参数

​ awk脚本内的变量可以在命令行中进行赋值,实现向awk脚本传递参数;

​ 参数赋值放在脚本之后、输入文件之前:

awk脚本   parameter=value  输入文件
  • 注意

    awk命令行参数不能被BEGIN字段语句访问,即直到输入文件的第1行被读取时,命令行参数方才生效。

    原因:awk读到命令行参数的赋值语句时,并不知道这是一个命令行参数的赋值语句,而认为这是一个文件名,当然这个文件名是无效的,awk继续读取后面的参数,直到一个正确的输入文件名被解析的时候,awk才判定前面的语句是命令行参数的赋值语句。

    awk 'BEGIN {print n} {if (n==1) print "Reading the first file!"}' n=1 /etc/passwd

2.9 条件语句和循环语句

  • 条件语句

    if (条件表达式)
    	动作1
    [else 
    	动作2]
  • 循环语句

    • while

      while (条件表达式)
      	动作
    • do while

      do
      	动作
      while (条件表达式)
    • for

      for (设置计数器初值;测试计数器;计数器变化)
      	动作

2.10 数组

​ 数组是用于存储一系列值的变量,这些值之间通常是有联系的,可以通过索引来访问数组的值,索引需要用中括号括起来。

  • 数组的基本格式

    array[index]=value

    awk数组无须定义数组类型和大小,而可以直接赋值后使用。

    # split函数的返回值是数组的大小
    # split(r,s,t)函数将字符串以t为分隔符,将r字符串拆分为字符串数组,并存放在t中
    awk 'BEGIN {print split("adb/dec/xyz",str,"/")}'
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值