Skip to content
KARINKARIN
博客主页
项目总览
知识要点
捣鼓折腾
Git笔记
Excel修炼秘籍
github icon
  • 博客主页
    • 项目总览
          • Shell脚本笔记
            • Shell脚本介绍
              • Shell语法
                • Shell格式化输出
                  • Shell格式化输入
                    • Shell变量
                      • Shell数组
                        • Shell运算
                          • Shell流程控制---if判断语句
                            • Shell流程控制---for循环语句
                              • Shell流程控制---while循环语句
                                • Shell流程控制---until循环语句
                                  • Shell流程控制---case分支语句
                                    • Shell函数
                                      • Shell正则表达式
                                        • Shell对文本的搜索---grep命令
                                          • Shell对文件的操作---sed命令
                                            • Shell对输出流的处理---awk命令
                                              • awk 介绍
                                                • awk 命令格式
                                                • awk 的基本用法
                                                  • awk 对字段的提取(列)
                                                    • awk 对记录的提取(行)
                                                      • awk 命令选项详解
                                                        • awk 对字符串的提取(行列交汇)
                                                          • awk 程序的优先级
                                                            • 优先级显示
                                                            • awk 高级用法
                                                              • awk 定义数组
                                                                • awk 运算
                                                                  • awk 环境变量
                                                                    • 流程控制
                                                                    • awk小技巧
                                                                    • Shell监控脚本
                                                                      • Shell脚本---lamp环境安装

                                                                    Shell对输出流的处理---awk命令

                                                                    author iconkarincalendar icon2021年4月9日category icon
                                                                    • 教程
                                                                    tag icon
                                                                    • shell
                                                                    timer icon大约 8 分钟

                                                                    此页内容
                                                                    • awk 介绍
                                                                      • awk 命令格式
                                                                    • awk 的基本用法
                                                                      • awk 对字段的提取(列)
                                                                      • awk 对记录的提取(行)
                                                                      • awk 命令选项详解
                                                                      • awk 对字符串的提取(行列交汇)
                                                                      • awk 程序的优先级
                                                                      • 优先级显示
                                                                    • awk 高级用法
                                                                      • awk 定义数组
                                                                      • awk 运算
                                                                      • awk 环境变量
                                                                      • 流程控制
                                                                    • awk小技巧

                                                                    在日常计算机管理中,总会有很多数据输出到屏幕或者文件,这些输出包含了标准输出、标准错误输出。默认情况下,这些信息全部输出到默认输出设备---屏幕。然而,大量的数据输出中,只有一小部分是我们需要重点关注的,把我们需要的或关注的这些信息,过滤或者提取,以备后续需要是调用。早先的学习中,我们学过使用 grep 来过滤这些数据,使用 cut、tr 命令提取某些字段,但是它们都不具备提取并处理数据的能力,都必须先过滤,再提取转存到变量,然后再通过变量提取去处理。

                                                                    比如:内存使用率的统计步骤

                                                                    通过 free -m 提取出内存总量,赋值给变量 memory_totle

                                                                    通过 free -m 提取出内存使用量,赋值给变量 memory_use

                                                                    通过数学运算,计算出内存使用率

                                                                    需要执行多步才能得到内存使用率,那么有没有一个能够集过滤、提取、运算为一体的命令呢?当然,就是我们即将学习的 awk 命令。

                                                                    # awk 介绍

                                                                    awk 是一种可以处理数据、产生格式化报表的语言,功能十分强大。awk 认为文件中的每一行是一条记录,记录与记录之间的分割符为换行符;每一列是一个字段,字段与字段的分割符默认是一个或多个的空格或 tab 制表符。

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

                                                                    # awk 命令格式

                                                                    [root@localhost ~]# awk [选项] [BEGIMN]{program}[END] [file]
                                                                    选项:
                                                                    	-F	:fs指定描绘一行中数据字段的分割符,默认为空格
                                                                    	-f	:指定读取程序的文件名
                                                                    	-v	:定义awk程序中使用的变量和默认值
                                                                    	
                                                                    程序运行优先级:
                                                                    	BEGIN	:在开始处理数据之前执行,可选项
                                                                    	program	:如何处理数据流,必选项
                                                                    	END		:处理完数据流后执行,可选项
                                                                    	
                                                                    注意:
                                                                    	awk 程序脚本由左大括号和右大括号定义。脚本命令必须防止在两个大括号之间。由于 awk 命令行假定脚本是单文本字符串,还必须将脚本放在单引号中。
                                                                    
                                                                    1
                                                                    2
                                                                    3
                                                                    4
                                                                    5
                                                                    6
                                                                    7
                                                                    8
                                                                    9
                                                                    10
                                                                    11
                                                                    12
                                                                    13

                                                                    # awk 的基本用法

                                                                    # awk 对字段的提取(列)

                                                                    字段提取:提取一个文本中的一列数据并打印输出 字段相关内置变量

                                                                    $0 表示正行文本

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

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

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

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

                                                                    • 读入test文件每行数据并把每行数据打印出来
                                                                    [root@linux ~ ]# 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
                                                                    
                                                                    1
                                                                    2
                                                                    3
                                                                    4
                                                                    5
                                                                    6
                                                                    • 打印test文件的第六个字段
                                                                    [root@linux ~ ]# awk '{print $6}' test
                                                                    jumps
                                                                    jumps
                                                                    jumps
                                                                    jumps
                                                                    jumps
                                                                    
                                                                    1
                                                                    2
                                                                    3
                                                                    4
                                                                    5
                                                                    6
                                                                    • 打印test文件的最后一个字段
                                                                    [root@linux ~ ]# awk '{print $NF}' test
                                                                    dog
                                                                    dog
                                                                    dog
                                                                    dog
                                                                    dog
                                                                    
                                                                    1
                                                                    2
                                                                    3
                                                                    4
                                                                    5
                                                                    6

                                                                    # awk 对记录的提取(行)

                                                                    记录提取:提取一个文本中的一行并打印输出 记录的提取方法有两种:

                                                                    1. 通过行号
                                                                    2. 通过正则匹配
                                                                    • NR:指定行号

                                                                    提取 test 中的第三行(指定行号为3)

                                                                    [root@localhost ~ ]# awk 'NR==3{print $0}' test
                                                                    3 the quick brown fox		 jumps over the lazy cat . dog
                                                                    [root@localhost ~ ]# awk 'NR==1{print $1,$3,$5}' /etc/passwd
                                                                    root 0 root
                                                                    [root@localhost ~ ]# awk 'NR==1{print $1 "-" $3 "-" $5}' /etc/passwd
                                                                    root-0-root
                                                                    
                                                                    1
                                                                    2
                                                                    3
                                                                    4
                                                                    5
                                                                    6

                                                                    # awk 命令选项详解

                                                                    • -F:指定字段与字段的分割符

                                                                    当输出的数据流字段格式不是 awk 默认的字段格式时,我们可以使用 -F 命令选项来重新定义数据流字段分割符号。比如:

                                                                    [root@localhost ~ ]# awk -F ':' '{print $1,$3,$NF}' /etc/passwd
                                                                    root 0 /bin/bash
                                                                    daemon 1 /usr/sbin/nologin
                                                                    ......
                                                                    karin 1000 /bin/bash
                                                                    sshd 122 /usr/sbin/nologin
                                                                    
                                                                    1
                                                                    2
                                                                    3
                                                                    4
                                                                    5
                                                                    6
                                                                    • -f:如果 awk 命令是日常重复工作,而又没有太多变化,可以将程序写入文件,每次使用-f调用程序文件就可以了,方便且高效。
                                                                    [root@localhost ~ ]# vim abc
                                                                    {print $1,$1,$NF}
                                                                    [root@localhost ~ ]# awk -f abc test
                                                                    1 quick dog
                                                                    2 quick dog
                                                                    3 quick dog
                                                                    4 quick dog
                                                                    5 quick dog
                                                                    
                                                                    1
                                                                    2
                                                                    3
                                                                    4
                                                                    5
                                                                    6
                                                                    7
                                                                    8
                                                                    • -v:定义变量,既然作者写awk的时候就是按着语言去写的,那么语言中最重要的要素---变量肯定不能缺席,所以可以使用 -v 命令选项定义变量
                                                                    [root@localhost ~ ]# awk -v name='root' 'BEGIN{print name}'
                                                                    root
                                                                    
                                                                    1
                                                                    2

                                                                    # awk 对字符串的提取(行列交汇)

                                                                    记录和字段的汇合点就是字符串 打印 test 第三行的第六个字段

                                                                    [root@localhost ~ ]# awk 'NR==3{print $6}' test
                                                                    jumps
                                                                    
                                                                    1
                                                                    2

                                                                    # awk 程序的优先级

                                                                    关于 awk 程序的优先级,BEGIN 是优先级最高的代码块,是在执行 program 之前执行的,不需要提供数据源,因为不涉及到任何数据处理,也不依赖于 program 代码块;program 代码块是对数据流干什么,是必选代码块,也是默认代码块。所以在执行时必须提供数据源;END 是处理完数据流后的操作,如果需要执行 END 代码块,就必须需要 program 的支持,单个无法执行。

                                                                    # 优先级显示

                                                                    [root@localhost ~ ]# awk 'BEGIN{print "hello world"}{print $0}END{print "bye bye"}' test
                                                                    hello world
                                                                    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
                                                                    bye bye
                                                                    
                                                                    1
                                                                    2
                                                                    3
                                                                    4
                                                                    5
                                                                    6
                                                                    7
                                                                    8
                                                                    • 不需要数据源,可以直接执行
                                                                    [root@localhost ~ ]# awk 'BEGIN{print "hello world"}'
                                                                    hello world
                                                                    
                                                                    1
                                                                    2
                                                                    • 没有提供数据源,所以无法执行成功
                                                                    [root@localhost ~ ]# awk '{print "hello world"}'
                                                                    [root@localhost ~ ]# awk 'END{print "hello world"}'
                                                                    
                                                                    1
                                                                    2

                                                                    # awk 高级用法

                                                                    awk 是一门语言,那么就会符合语言的特性,除了可以定义变量外,还可以定义数组,还可以进行运算,流程控制。

                                                                    # awk 定义数组

                                                                    数组定义方式:

                                                                    数组名[索引]=值
                                                                    
                                                                    1

                                                                    定义数组 array,有两个元素,分别是 100,200,打印数组元素。

                                                                    [root@localhost ~ ]# awk 'BEIGN{array[0]=100;array[1]=200;print array[0],array[1]}'
                                                                    100 200
                                                                    
                                                                    1
                                                                    2

                                                                    # awk 运算

                                                                    赋值运算 =

                                                                    比较运算 >、>=、==、<=、<、!=

                                                                    数学运算 +、-、*、/、%、**、++、--

                                                                    逻辑运算 &&、||

                                                                    匹配运算 、!

                                                                    • 赋值运算:主要是对变量或者数组赋值
                                                                    [root@localhost ~ ]# read -2 /proc/meminfo | awk 'NR==1{t=$2}NR==2{f=$2;print (t-f)*100/t "%"}'
                                                                    8.7528%
                                                                    
                                                                    1
                                                                    2
                                                                    • 比较运算:如果比较字符串则按 ascii 编码顺序表比较,比较结果 1 则为真,0 则为假
                                                                    [root@localhost ~ ]# awk 'BEGIN{print "a" >= "b" }'
                                                                    0
                                                                    [root@localhost ~ ]# awk 'BEGIN{print 99 >= 1 }'
                                                                    1
                                                                    
                                                                    1
                                                                    2
                                                                    3
                                                                    4
                                                                    • 数学运算:支持幂运算,支持小数点
                                                                    [root@localhost ~ ]# awk 'BEGIN{print 9-1 }'
                                                                    8
                                                                    [root@localhost ~ ]# awk 'BEGIN{print 100%3 }'
                                                                    1
                                                                    
                                                                    1
                                                                    2
                                                                    3
                                                                    4
                                                                    • 逻辑运算:与、或运算
                                                                    [root@localhost ~ ]# awk 'BEGIN{print 100>3 && 28<=9 }'
                                                                    0
                                                                    
                                                                    1
                                                                    2
                                                                    • 匹配运算:精确匹配 ,精确不匹配 !;模糊匹配 ~,模糊不匹配 !~
                                                                    [root@localhost ~ ]# awk -F: '$1=="root"{print $0}' /etc/passwd
                                                                    root:x:0:0:root:/root:/bin/bash
                                                                    
                                                                    1
                                                                    2

                                                                    # awk 环境变量

                                                                    变量描述
                                                                    FIELDWIDTHS以空格分隔的数字列表,用空格定义每个数据字段的精确宽度
                                                                    FS输入字段分隔符号
                                                                    OFS输出字段分隔符号
                                                                    RS输入记录分隔符号
                                                                    ORS输出记录分隔符号

                                                                    FIELDWIDTHS:重新定义列宽并打印,注意不可以使用 $0 打印所有,因为 $0 是打印本行全内容,不会打印你定义的字段

                                                                    [root@localhost ~ ]# awk 'BEGIN{FIELDWIDTHS="5 2 8"}NR==1{print $1,$2,$3}' /etc/passwd
                                                                    root: x: 0:0:root
                                                                    
                                                                    1
                                                                    2

                                                                    FS:指定数据源中字段分隔符,类似命令选项 -F

                                                                    [root@localhost ~ ]# awk 'BEGIN{FS=":"}NR==1{print $1,$3,$NF}‘ /etc/passwd
                                                                    root 0 /bin/bash
                                                                    
                                                                    1
                                                                    2

                                                                    OFS:指定输出到屏幕后字段的分隔符

                                                                    [root@localhost ~ ]# awk 'BEGIN{FS=":";OFS="-"}NR==1{print $1,$3,$NF}' /etc/passwd
                                                                    root-0-/bin/bash
                                                                    
                                                                    1
                                                                    2

                                                                    RS:指定记录的分隔符,将记录的分隔符修改为空后,所有的行会变成一行

                                                                    [root@localhost ~ ]# awk 'BEGIN{RS=""}{print $1,$2,$3}' num
                                                                    1 2 3
                                                                    
                                                                    1
                                                                    2

                                                                    ORS:输出到屏幕后记录的分隔符,默认为回车

                                                                    [root@localhost ~ ]# awk 'BEGIN{RS="";ORS="*"}{print $1,$2,$3,$4,$5}' num
                                                                    1 2 3 4 5*[root@localhost ~ ]# 
                                                                    
                                                                    1
                                                                    2

                                                                    #可以看出,提示符和输出在一行了,因为默认回车换成了*(ORS="*")

                                                                    # 流程控制

                                                                    1. if 判断语句
                                                                    2. for 循环语句
                                                                    3. while 循环语句
                                                                    4. do...while 语句
                                                                    5. 循环控制
                                                                    • if 判断语句
                                                                    [root@localhost ~ ]# awk '{if ($1<5)print $1*2;else print $1/2}' num
                                                                    2
                                                                    4
                                                                    6
                                                                    8
                                                                    2.5
                                                                    3
                                                                    3.5
                                                                    4
                                                                    4.5
                                                                    5
                                                                    
                                                                    1
                                                                    2
                                                                    3
                                                                    4
                                                                    5
                                                                    6
                                                                    7
                                                                    8
                                                                    9
                                                                    10
                                                                    11
                                                                    • for 循环语句
                                                                    [root@localhost ~ ]# vim num2
                                                                    60 50 100
                                                                    150 30 10
                                                                    70 100 40
                                                                    [root@localhost ~ ]# awk '{sum=0;for (i=1;i<4;i++){sum+=$i}print sum}' sum2
                                                                    210
                                                                    190
                                                                    210
                                                                    
                                                                    1
                                                                    2
                                                                    3
                                                                    4
                                                                    5
                                                                    6
                                                                    7
                                                                    8
                                                                    • while 循环语句
                                                                    [root@localhost ~ ]# awk '{sum=0;i=1;while(i<4){sum+=$i;i++}print sum}' num2
                                                                    210
                                                                    190
                                                                    210
                                                                    
                                                                    1
                                                                    2
                                                                    3
                                                                    4
                                                                    • do...while 语句
                                                                    [root@localhost ~ ]# awk '{sum=0;i=1;do{sum+=$i;i++}while(i<4);print sum}' num2
                                                                    210
                                                                    190
                                                                    210
                                                                    
                                                                    1
                                                                    2
                                                                    3
                                                                    4
                                                                    • 循环控制语句

                                                                    break:跳出循环,继续执行后续语句。

                                                                    continue:停止本次循环,继续下一次循环。

                                                                    累加每行数值,和大于 150 停止累加

                                                                    [root@localhost ~ ]# awk '{
                                                                    > sum=0
                                                                    > i=1
                                                                    > while (i<4){
                                                                    > 	sum+=$i
                                                                    > 	if (sum>150){
                                                                    > 		break
                                                                    > 	}
                                                                    > 	i++
                                                                    > }
                                                                    > print sum
                                                                    > }' num2
                                                                    210
                                                                    180
                                                                    170
                                                                    
                                                                    1
                                                                    2
                                                                    3
                                                                    4
                                                                    5
                                                                    6
                                                                    7
                                                                    8
                                                                    9
                                                                    10
                                                                    11
                                                                    12
                                                                    13
                                                                    14
                                                                    15

                                                                    # awk小技巧

                                                                    • 打印 test 文本的行数
                                                                    [root@localhost ~ ]# awk 'END{print NR}' test
                                                                    5
                                                                    
                                                                    1
                                                                    2
                                                                    • 打印 test 文本最后一行内容
                                                                    [root@localhost ~ ]# awk 'END{print $0}' test
                                                                    5 the quick brown fox jumps over the lazy cat . dog
                                                                    
                                                                    1
                                                                    2
                                                                    • 打印 test 文本列数
                                                                    [root@localhost ~ ]# awk 'END{print NF}' test
                                                                    12
                                                                    
                                                                    1
                                                                    2
                                                                    edit icon编辑此页open in new window
                                                                    上一页
                                                                    Shell对文件的操作---sed命令
                                                                    下一页
                                                                    Shell监控脚本
                                                                    MIT Licensed
                                                                    Copyright © 2022 karin