zoukankan      html  css  js  c++  java
  • shell脚本(16)-awk命令

    文档目录

    一、awk介绍

    二、awk基本用法

    1、awk对字段(列)的提取:

    2、awk对记录(行)的提取:

    3、awk对字符串提取:

    4、awk程序的优先级:

    三、awk高级用法

    1、awk定义数组

    2、awk运算

    3、awk环境变量:

    4、流程控制

    四、awk小技巧

    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 分隔符- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 

    一、awk介绍

     1、shell对输出流的处理:

    日常计算机管理中,总会有很多数据输出到屏幕或者文件,这些输出包含了标准输出、标准错误输出,默认情况下,这些信息全部输出到屏幕,而其中只有一小部分是我们关注的内容,需要我们把关注的重点内容过滤或提取出来以备后续的使用。可以使用grep、cut、tr等命令过滤或提取数据,但是他们都不具备同时提取并处理数据的能力,而awk命令集过滤、提取、运算为一体,平行命令还有gawk、pgawk、dgawk。

    2、awk简介:

    awk是一种可以处理数据、产生格式化报表的语言,功能十分强大。

    awk认为文件中每一行是一条记录,记录之间分隔符为换行符,每一列是一个字段,字段之间的分隔符默认是一个或多个空格或tab制表符。

    awl的工作方式是读取数据,将每一行数据视为一条记录(record)每条记录以字段分隔符分为若干字段,然后输出各个字段的值

    3、awk语法:awk [options] [BNGIN] {program} [END][file]

    4、常用命令选项:

    -F fs 指定描绘一行中数据字段的文件分隔符,默认为空格

    -f file 指定读取程序的文件名

    -v var=value 定义awk程序中使用的变量喝默认值

    注意:awk程序脚本由左大括号和右大括号定义,脚本命令必须放置在两个大括号之间,由于awk假定程序脚本是单个文本字符串,因此必须还要将脚本放到单引号中。

    5、awk程序运行优先级是:

    1)BEGIN:在开始处理数据流之前执行,可选项

    2)program:如何处理数据流,必选项

    3)END:处理完数据流后执行,可选项

     

    二、awk基本用法

    [root@localhost test20210811]# cat test  #测试数据
    1 the quick brown fox jumps over the lazy cat . dog
    2 the quick brown fox jumps over the lazy cat . dog
    3 the quick brown fox         jumps over the lazy cat . dog
    4 the quick brown fox jumps over the lazy cat . dog
    5 the quick brown fox jumps over the lazy cat . dog

    1、awk对字段(列)的提取:

    字段提取:提取一个文本中的一列数据并打印输出:

    字段相关内置变量:

    $0:表示整行文本

    $1:表示文本中第一个数据字段

    $2:表示文本中第二个数据字段

    $N:表示文本中第N个数据字段

    $NF:表示文本行中的最后一个字段

    举例说明:

    [root@localhost test20210811]# awk '{print $0}' test  #打印全文本
    1 the quick brown fox jumps over the lazy cat . dog
    2 the quick brown fox jumps over the lazy cat . dog
    3 the quick brown fox         jumps over the lazy cat . dog
    4 the quick brown fox jumps over the lazy cat . dog
    5 the quick brown fox jumps over the lazy cat . dog
    [root@localhost test20210811]# awk '{print $NF}' test  #打印最后一列
    dog
    dog
    dog
    dog
    dog
    [root@localhost test20210811]# awk '{print $3}' test  #打印第3列
    quick
    quick
    quick
    quick
    quick
    [root@localhost test20210811]# awk -v name='mrwhite' 'BEGIN{print name}'  #定义变量,调用变量打印
    mrwhite

    2、awk对记录(行)的提取:

    记录提取:提取一个文本中的一行并打印输出

    记录的提取方法有两种:a、通过行号;b、正则匹配

    记录相关内置变量

    NR:指定行号

    举例说明:

    [root@localhost test20210811]# awk 'NR==3{print $0}' test  #打印第3行
    3 the quick brown fox         jumps over the lazy cat . dog
    [root@localhost test20210811]# awk 'END{print $0}' test  #打印最后1行
    5 the quick brown fox jumps over the lazy cat . dog

    3、awk对字符串提取:

    记录和字段的汇合点就是字符串

    [root@localhost test20210811]# awk -F " " 'NR==3{print "第3行第2个单词:"$2,"第3行第5个单词"$5}' test   #提取用户文件第3行的第2,5个字段并拼接语句,空格分隔
    第3行第2个单词:the 第3行第5个单词fox
    [root@localhost test20210811]# head -2 /proc/meminfo  #内存信息
    MemTotal:         995672 kB
    MemFree:          669620 kB
    [root@localhost test20210811]# head -2 /proc/meminfo | awk 'NR==1{t=$2}NR==2{f=$2;print(t-f)*100/t "%"}'  #打印内存使用率
    32.7751%

    4、awk程序的优先级:

    [BNGIN] -> {program}  -> [END] ,其中 {program}是必须包含的

    [root@localhost test20210811]# awk  'BEGIN{print "hello,let us start!"}NR==1{print $0}END{print "Bye Bye!"}' test  #在执行命令前后增加BEGIN于END语句
    hello,let us start!
    1 the quick brown fox jumps over the lazy cat . dog
    Bye Bye!
    [root@localhost test20210811]# awk 'BEGIN{print "helloworld"}'  #BEGIN可以单独执行,不需要数据流
    helloworld
    [root@localhost test20210811]# awk 'END{print "helloworld"}'  #END无法执行,需要数据流
    ^C
    [root@localhost test20210811]# awk '{print "helloworld"}'  #无法单独执行,需要数据流
    ^C

     

    三、awk高级用法

    1、awk定义数组

    数组定义方式:数组名[索引]=值

    [root@localhost test20210811]# awk 'BEGIN{array[1]="one";array[2]=500;print array[1],array[2]}'  #定义数组并打印
    one 500

    2、awk运算

    1)赋值运算 =

    [root@localhost test20210812]# awk 'BEGIN{name="bktest";print name}'  #BEGIN内赋值
    bktest
    [root@localhost test20210812]# awk -v name='bktest2' 'BEGIN{print name}'  #-v定义变量
    bktest2
    [root@localhost test20210812]# awk 'BEGIN{array[0]=100;print array[0]}'  #赋值数组
    100
    [root@localhost test20210812]#

    2)比较运算 >  >=  ==  <=  !=

    如果是字符串比较则按照ascii编码顺序比较,如果结果返回true则用1表示,返回false用0表示

    [root@localhost test20210812]# awk 'BEGIN{print "d">"b" }'  #字符串比较
    [root@localhost test20210812]# awk 'BEGIN{print "a">="b" }'  #字符串比较
    0
    [root@localhost test20210812]# awk 'BEGIN{print "a"<"b" }'  #字符串比较
    1
    [root@localhost test20210812]# seq 1 10 > num  #1到10输出到num文件
    [root@localhost test20210812]# awk '$1>=8{print $0}' num #将大于等于8的数字打印
    8
    9
    10
    [root@localhost test20210812]# awk '$1==5{print $0}' num #将等于5的打印出
    5

    3)数据运算 +  -  *  /  %  **  ++  --

    [root@localhost test20210812]# awk 'BEGIN{print 1+1}' #计算加法
    2
    [root@localhost test20210812]# awk 'BEGIN{print 100-50}' #计算加法
    50
    [root@localhost test20210812]# awk 'BEGIN{print 100/3}' #计算乘法
    33.3333
    [root@localhost test20210812]# awk 'BEGIN{print 1+1}' #计算加法
    2
    [root@localhost test20210812]# awk 'BEGIN{print 100-50}' #计算减法
    50
    [root@localhost test20210812]# awk 'BEGIN{print 100*3}' #计算乘法
    300
    [root@localhost test20210812]# awk 'BEGIN{print 5/3}' #计算除法
    1.66667
    [root@localhost test20210812]# awk 'BEGIN{print 2**3}'  #计算2的三次方
    8
    [root@localhost test20210812]# awk 'BEGIN{print 100%3}'  #计算取余数
    1

    4)逻辑运算 &&  ||

    [root@localhost test20210812]# awk 'BEGIN{print 100>=2 && 100>=3}'  #且关系
    1
    [root@localhost test20210812]# awk 'BEGIN{print 100>=2 && 5<2}'     #且关系
    0
    [root@localhost test20210812]# awk 'BEGIN{print 100>=2 || 5<2}'     #或关系
    1

    5)匹配运算 == ~  ~!

    [root@localhost test20210812]# awk -F: '$1=="root"{print $0}' /etc/passwd   #精确匹配
    root:x:0:0:root:/root:/bin/bash
    [root@localhost test20210812]# awk -F: '$1~"w"{print $0}' /etc/passwd   #模糊匹配
    shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
    systemd-network:x:192:192:systemd Network Management:/:/sbin/nologin

    3、awk环境变量:

    变量 描述
    FILEDWIDTH 以空格分隔的数字列表,用空格定义每个数据字段的精确宽度
    FS 输入字段分隔符号(数据源-列)
    OFS 输出字段分隔符号(打印屏幕-列)
    RS 输入记录分隔符(数据源-行)
    ORS 输出记录分隔符号(打印屏幕-行)

     举例说明:

    [root@localhost test20210812]# head -1 /etc/passwd
    root:x:0:0:root:/root:/bin/bash
    [root@localhost test20210812]# awk 'BEGIN{FIELDWIDTHS="5 2 8"}NR==1{print $1,$2,$3}'  /etc/passwd   #指定打印3列,第1,2,3列分别打印5,2,8个字符
    root: x: 0:0:root
    [root@localhost test20210812]# awk 'BEGIN{FS=":"}{print $1}'  /etc/passwd | head -3   #按照数据库:分隔打印第1列
    root
    bin
    daemon
    [root@localhost test20210812]# awk 'BEGIN{FS=":"}{print $1,$3,$5}'  /etc/passwd | head -3   #按照数据库:分隔打印第1,3,5列,空格分隔
    root 0 root
    bin 1 bin
    daemon 2 daemon
    [root@localhost test20210812]# awk 'BEGIN{FS=":"}{print $1"-"$3"-"$5}'  /etc/passwd | head -3   #按照数据库:分隔打印第1,3,5列,-分隔
    root-0-root
    bin-1-bin
    daemon-2-daemon
    [root@localhost test20210812]# awk 'BEGIN{FS=":";OFS="-"}{print $1,$3,$5}'  /etc/passwd | head -3   #按照数据库:分隔打印第1,3,5列,指定-分隔
    root-0-root
    bin-1-bin
    daemon-2-daemon
    [root@localhost test20210812]# seq 1 3 >num;cat num  #构造数据
    1
    2
    3
    [root@localhost test20210812]# awk 'BEGIN{RS=""}{print $1,$2,$3}' num  #指定数据源的数据分隔符为空格
    1 2 3
    [root@localhost test20210812]# awk 'BEGIN{RS="";ORS="####"}{print $1,$2,$3}' num  #指定数据源的数据分隔符为空格,输出时行分隔为####
    1 2 3####[root@localhost test20210812]#

    4、流程控制

    1)if判断语句

    [root@localhost test20210813]# seq 0 3 >num  #构造数据0-3
    [root@localhost test20210813]# awk '{if($1>2)print $0}' num  #打印>2的行
    3
    [root@localhost test20210813]# awk '{if($1<1)print $0}' num  #打印<1的行
    0
    [root@localhost test20210813]# awk '{if($1<2)print $1*10;else print $1/10}' num   #前两行*10,其他/10
    0
    10
    0.2
    0.3

    2)for循环语句

    [root@localhost test20210813]# cat num2  #构造数据
    60 50 100
    150 30 10
    70 100 40
    [root@localhost test20210813]# awk '{for(i=1;i<4;i++){sum=$1+$2+$3}print sum}' num2  #每行累加
    210
    190
    210
    [root@localhost test20210813]# awk '{sum=0;for(i=1;i<4;i++){sum+=$i}print sum}' num2  #每行累加,第二种写法
    210
    190
    210

    3)while循环语句

    [root@localhost test20210813]# cat num2  #构造数据
    60 50 100
    150 30 10
    70 100 40
    [root@localhost test20210813]# awk '{sum=0;i=1;while(i<4){sum+=$i;i++}print sum}' num2 #每行累加 210 190 210

    4)do...while语句

    [root@localhost test20210813]# cat num2  #构造数据
    60 50 100
    150 30 10
    70 100 40
    [root@localhost test20210813]# awk '{sum=0;i=1;do{sum+=$i;i++}while(i<4)print sum}' num2  #每行累加
    210
    190
    210

    5)循环控制(break跳出循环)

    [root@localhost test20210813]# cat num2  #构造数据
    60 50 100
    150 30 10
    70 100 40
    [root@localhost test20210813]# awk '{sum=0;i=1;while(i<4){sum+=$i;if(sum>=180)break}i++;print sum}' num2 #每行累加,大于等于180停止
    180
    300
    210
    [root@localhost test20210813]# awk '{sum=0;i=1;while(i<4){sum+=$i;if(sum>=180)break;i++}print sum}' num2 #每行累加,大于等于180停止
    210
    180
    210

    四、awk小技巧

    1、打印文本的行数

    [root@localhost test20210813]# awk 'END{print NR}' /etc/passwd   #打印行数
    21

    2、打印文本最后一行的内容

    [root@localhost test20210813]# awk 'END{print $0}' /etc/passwd   #打印文本最后一行内容
    apache:x:48:48:Apache:/usr/share/httpd:/sbin/nologin

    3、打印文本列数

    [root@localhost test20210813]# cat num2  #构造数据
    60 50 100
    150 30 10
    70 100 40
    [root@localhost test20210813]# awk 'END{print NF}' num2  #打印文本列数
    3

    4、awk 中的大小写转化函数

    [root@localhost test20210813]# echo | awk '{ print toupper("test"), tolower("TEST") }'
    TEST test

    5、去重并统计次数

    [root@localhost test20210813]# cat num3  #测试数据
    a 0
    b 3
    c 1
    a 5
    b 2
    c 3
    d 7
    a 1
    [root@localhost test20210813]# awk '{print $0}' num3 | awk '{h[$1]++}END{for(i in h)print i,h[i]}'  #去重统计次数
    a 3
    b 2
    c 2
    d 1

    6、去重并求和

    [root@localhost test20210813]# cat num3  #测试数据
    a 0
    b 3
    c 1
    a 5
    b 2
    c 3
    d 7
    a 1
    [root@localhost test20210813]# awk '{print $0}' num3 | awk '{h[$1]=h[$1]+$2}END{for(i in h)print i,h[i]}'  #去重求和
    a 6
    b 5
    c 4
    d 7

    7、截取字符串

    [root@localhost test20210813]# echo '1234567890' > num4 #构造测试数据
    [root@localhost test20210813]# awk '{print substr($0,1,6)}' num4  #截取字符串
    123456

    8、awk找出两个文件中相同的行

    [root@localhost test20210813]# cat file1  #测试数据1
    1111
    2222
    4444
    5555
    [root@localhost test20210813]# cat file2  #测试数据2
    1111
    3333
    4444
    5555
    [root@localhost test20210813]# awk 'NR==FNR{a[$0]++} NR>FNR&&a[$0]' file1 file2 > same.txt  #记录文件相同的行
    [root@localhost test20210813]# cat same.txt 
    1111
    4444
    5555

    9、awk找出文件1在文件2没有的值

    [root@localhost test20210813]# cat file1  #测试数据1
    1111
    2222
    4444
    5555
    [root@localhost test20210813]# cat file2  #测试数据2
    1111
    3333
    4444
    5555
    [root@localhost test20210813]# awk 'NR==FNR{a[$0]++} NR>FNR&&!a[$0]'  file1 file2 > lack.txt  #记录文件1在文件2没有的值
    [root@localhost test20210813]# cat lack.txt 
    3333
  • 相关阅读:
    AtCoder 杂题乱写
    JOISC2020 遗迹
    【考试总结】20220107
    AGC021F Trinity
    CCPC2021 广州A/CF Gym103415A
    【考试总结】20220115
    JDK8 时间api当天的开始和截至时间
    技术方案模板
    正则表达式
    组合算法
  • 原文地址:https://www.cnblogs.com/mrwhite2020/p/15022039.html
Copyright © 2011-2022 走看看