文本处理三剑客之awk

awk工作模式介绍

  • 简介

    1. awk是一个文本处理工具,通常用于处理数据并生成结果报告
    2. awk的命名是它的创始人Alfred Aho 、Peter Weinberger、和Brian Kernighan姓氏的首个字母组成。
  • 工作模式

  • 语法格式:

    1. awk 'BEGIN{}pattern{commonds}END{}' file_name

    2. standard output | awk 'BEGIN{}pattern{commonds}END{}'

    3. 语法格式说明

      语法格式解释
      BEGIN{}正式处理数据之前执行
      pattern匹配模式
      {commands}处理命令,可能多行
      END{}处理完所有匹配数据后执行

awk的内置变量

  • 内置变量对照表

    内置变量含义
    $0整行内容
    1   1~ 1 n当前行的1~n个字段
    NF当前行的字段个数,也就是有多少列
    NR当前行的行号,从1开始计数
    FNR多文件处理时,每个文件行号单独计数,都是从0开始
    FS输入字段分隔符。不指定默认为空格或tab键分割
    RS输入行分隔符。默认回车换行(\n)
    OFS输出字段分隔符。默认为空格
    ORS输出行分隔符。默认为回车换行
    FILENAME处理文件的文件名
    ARGC命令行参数个数
    ARGV命令行参数数组
  • 例1:

  • 例2:


awk格式化输出之printf

  • printf的格式说明符

    格式符
    %s打印字符串
    %d打印十进制数
    %f打印一个浮点数
    %o打印八进制数
    %e打印数字的科学计数法形式
    %x打印十六进制数
    %c打印单个字符的ASCII码
    -左对齐
    +右对齐
    #显示8进制在前面加0,显示16进制在前面加0x
  • 示例:

    • 以字符串格式打印/etc/passwd中的第7个字段,以":"作为分隔符

      awk 'BEGIN{FS=":";OFS=":"}{printf "%s",$7}' /tec/passwd

    • 以10进制格式打印/etc/passwd中的第三个字段,以":"作为分隔符

      awk 'BEGIN{FS=":";}{printf "%d",$3}' /etc/passwd

    • 以浮点数格式打印/etc/passwd中的第三个字段,以":"作为分隔符

      awk 'BEGIN{FS=":";}{printf "%6.2f",$3}' /etc/passwd

    • 以16进制数格式打印/etc/passwd中的第三个字段,以":"作为分隔符

      awk 'BEGIN{FS=":";}{printf "%x",$3}' /etc/passwd

    • 以8进制数格式打印/etc/passwd中的第三个字段,以":"作为分隔符

      awk 'BEGIN{FS=":";}{printf "%o",$3}' /etc/passwd

    • 以科学计数法格式打印/etc/passwd中的第三个字段,以":"作为分隔符

      awk 'BEGIN{FS=":";}{printf "%.2e",$3}' /etc/passwd


awk模式匹配的两种工作模式

  • 模式匹配的两种用法

    1. 第一种:RegExp
    2. 第二种:关系运算匹配
  • 用法格式对照表

    语法格式含义
    RegExp按正则表达式匹配
    关系运算按关系运算匹配
  • 关系运算符匹配

    运算符含义
    <小于
    >大于
    <=小于等于
    >=大于等于
    ==等于
    !=不等于
    ~匹配正则表达式
    !~不匹配正则表达式
  • RegExp匹配

    • 将/etc/passwd中包含root的行输出

      awk 'BEGIN{FS=":";}/root/{print $0}' /etc/passwd

    • 将/etc/passwd中以yarn开头的行输出

      awk 'BEGIN{FS=":";}/^yarn/{print $0}' /etc/passwd

  • 布尔运算符匹配

    ||
    &&
  • 范例:

    • 以:为分隔符,匹配/etc/passwd文件中第三个字段小于50的行所有信息

      awk 'BEGIN{FS=":"}$3<50{print $0} /etc/passwd'

    • 以:为分隔符,匹配/etc/passwd文件中第三个字段大于50的行所有信息

      awk 'BEGIN{FS=":"}$3>50{print $0} /etc/passwd

    • 以:为分隔符,匹配/etc/passwd文件中第7个字段为/bin/bash的行所有信息

      awk 'BEGIN{FS=":"}$7=="/bin/bash"{print $0}' /etc/passwd

    • 以:为分隔符,匹配/etc/passwd文件中第7个字段为/bin/bash的行所有信息

      awk 'BEGIN{FS=":"}$7!="/bin/bash"{print $0}' /etc/passwd

    • 以:为分隔符,匹配/etc/passwd文件中第三个字段有3个数字的行所有信息

      awk 'BEGIN{FS=":"}$3~/[0-9]{3,}/' /etc/passwd

    • 以:为分隔符,匹配/etc/passwd文件中的行中没有/sbin/nologin的

      awk 'BEGIN{FS=":"}$0!~/\/sbin\/nologin/{print $0}' /etc/passwd

    • 以:为分隔符,匹配/etc/passwd中包含hdfs或yarn的所有行信息

      awk 'BEGIN{FS=":"}$1=="hdfds" || $1=="yarn" {print $0}' /etc/passwd

    • 以:为分隔符,匹配/etc/passwd中第三个字段小于50并且第四个字段大于50的所有行信息

      awk 'BEGIN{FS=":"}$3<50 && $4>50 {print $0}' /etc/passwd


awk动作中的表达式用法

  • awd动作表达式中的算术运算符

    运算符含义
    +
    -
    *
    /
    %
    ^或**乘方
    ++x
    x++
    –x
    x–
  • 范例:

    • 使用awk计算/etc/services中的空白行的数量

      awk 'BEGIN{sum=0;}/^$/{sum++;}END{print sum;}' /etc/services

    • 计算/etc/passwd文件中第三个字段的平均值

      awk 'BEGIN{FS=":";sum=0;count=0;}{sum=sum+$3;count++}END{print sum/count}' /etc/passwd


awk动作中的条件及循环语句

  • 条件语句

    if (条件表达式){
    	动作1
    }
    else if (条件表达式){
    	动作2
    }
    else{
    	动作3
    }
    
  • 范例:

  • 循环语句

    do{
        动作
    }while(条件表达式)
    
    for(初始化计数器;计数器测试;计数器变更){
        动作
    }
    
    while(条件表达式){
        
    }
    
  • 范例:

    计算1+2+3+……+100的和

    #for循环实现
    BEGIN{
    	sum=0;
    	for(i=1;i<101;i++)
    	{
    		sum+=i;	
    	}
    	printf "%s=%d","1+2+3+……+100",sum
    }
    //while循环实现
    BEGIN{
        sum=0;
        idx=1;
        while(idx<=100){
            sum=sum+idx;
        }
        printf "%s=%d","1+2+3+……+100",sum
    }
    #do while实现
    BEGIN{
        sum=1;
        idx=1;
        do{
    	idx++;
            sum=sum+idx;
        }while(idx<100)
        printf "%s=%d","1+2+3+……+100",sum
    }
    

awk中的字符串函数

函数名解释函数返回值
length(str)计算中字符串的长度整数长度值
index(str1,str2)在str1中查找str2的位置返回值为位置索引
tolower(str)转换为小写转换后的小写字符串
toupper(str)转换为大写转换后的大写字符串
substr(str)从字符串的m个位置开始,截取n位截取后的子串
split(str,arr,fs)按fs切割字符串,结果保存arrj截取后字串的个数
match(str,RE)在str中按照RE查找,返回位置f返回索引位置
sub(RE,RepStr,str)在str中搜索符合RE的字串,将其替换为RepStr,只替换第一个替换的个数
gsub(RE,RepStr,str)在str中搜索符合RE的字串,将其替换为RepStr,只替换所有替换的个数
  • ​ 范例:

    • 以:为分隔符,返回/etc/passwd中每行中每个字段的长度

    • 搜索字符串"I have a dream"中出现"ea"字符串的位置

    • 搜索字符串"Tranction 2345 Start:Select * from master" 第一个数字出现的位置

    • 截取字符串"tranaction start"的字串,从第4个字符开始,截取5位

    • 替换字符串"Tranction 234 Start,Event ID:9002"中第一个匹配到的数字为$

      awk 'BEGIN{str="Tranction 234 Start,Event ID:9002";sub(/[0-9]+/,"\$",str);print str}'


awk中的常用选项

选项解释
-v参数传递
-f指定脚本文件
-F指定分隔符
-V查看awk的版本号
  • 范例:
    • 例1:awk -v var1="hellow world" 'BEGIN{num=666;print num,var1}'
    • 例2:awk -F : '{print $1}' /etc/passwd

awk中数组的用法

  • 定义一个数组

    awk 'EGIN{arr[1]="ZhangSan1";arr[2]="ZhangSan2";arr[3]="ZhangSan3"};print arr[2]'

  • awk数组的下标不仅仅可以是数字,还可以是任意字符串,其实,awk中的数组本来就是关联数组,但用数字做下标时,awk也会默认把数字下标转换成字符串,所以它本质上还是一个使用字符串作为下标的***关联数组***。

  • 删除数组中的元素

    delete arr[1];delete arr

  • 判断元素是否为空(数组的元素设置为空,是允许的,当数组中没有某个元素而直接引用它的时候,它默认被赋值为空)

    awk 'EGIN{arr[1]="ZhangSan1";arr[2]="ZhangSan2";arr[3]="ZhangSan3"};if(3 in arr) print "three"

  • 数组的遍历

    awk 'EGIN{arr[1]="ZhangSan1";arr[2]="ZhangSan2";arr[3]="ZhangSan3"};for (i in arr) {print arr[i]}'

  • 在awk中,字符串和空字符串在参与运算时也会被当做数字0,之前我们说过,当我们引用数组中一个不存在的元素,元素被赋值成空字符串,当对这个元素进行自加运算时,元素的值就变成了1,因此当我们对一个不存在的元素进行自加运算后,这个元素的值就变成了自加的次数,自加x次,元素的值就被赋值为x,自加y次元素的值就被赋值为y,所以我们可以通过awk数组的这个特性来统计文本中某字符串出现的次数。

    #统计文本中人名出现的次数、
    awk '{for(i=1;i<=NF;i++){count[$i]++} }END{for(j in count)\
    {print j , count[j]}}' text
    

shell中数组的用法

  • 定义一个数组:

    arr={"Allen" "Mike" "Messi" "Jerry" "Hanmeimei" "WangLin"}

  • 打印元素

    echo ${arr[2]}

  • 打印元素的个数

    echo ${#arr[@]}

  • 打印元素的长度

    echo ${#arr[3]}

  • 给元素赋值

    arr[4]="LiSi"

  • 删除元素

    unset arr[2];unset arr

  • 分片访问

    echo ${arr[@]:1:3}

  • 元素内容替换

    ${arr[@/e/E]} 只替换第一个e;${arr[@//e/E]} 替换所有的e

  • 数组的遍历

    for a int arr
    do
    	echo $a
    done
    
  • 注意:

    1. shell中的数组下标是从0开始的

    2. @*在数组中都可以表示匹配所有元素

    3. #表示其后元素的长度

    4. 当我们使用unset删除数组中的单个元素时,其他元素还是使用初始的下标

      arr={"aaa" "bbb" "ccc" "ddd" "eeee"}
      
      echo ${arr[1]}
      
      unset arr[0]
      
      echo ${arr[1]}
      

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值