AI智能
改变未来

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 . dog2 the quick brown fox jumps over the lazy cat . dog3 the quick brown fox         jumps over the lazy cat . dog4 the quick brown fox jumps over the lazy cat . dog5 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 . dog2 the quick brown fox jumps over the lazy cat . dog3 the quick brown fox         jumps over the lazy cat . dog4 the quick brown fox jumps over the lazy cat . dog5 the quick brown fox jumps over the lazy cat . dog[root@localhost test20210811]# awk \'{print $NF}\' test  #打印最后一列dogdogdogdogdog[root@localhost test20210811]# awk \'{print $3}\' test  #打印第3列quickquickquickquickquick[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 kBMemFree:          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 . dogBye 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的数字打印8910[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/shutdownsystemd-network:x:192:192:systemd Network Management:/:/sbin/nologin

3、awk环境变量:

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

举例说明:

[root@localhost test20210812]# head -1 /etc/passwdroot: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列rootbindaemon[root@localhost test20210812]# awk \'BEGIN{FS=\":\"}{print $1,$3,$5}\'  /etc/passwd | head -3   #按照数据库:分隔打印第1,3,5列,空格分隔root 0 rootbin 1 bindaemon 2 daemon[root@localhost test20210812]# awk \'BEGIN{FS=\":\"}{print $1\"-\"$3\"-\"$5}\'  /etc/passwd | head -3   #按照数据库:分隔打印第1,3,5列,-分隔root-0-rootbin-1-bindaemon-2-daemon[root@localhost test20210812]# awk \'BEGIN{FS=\":\";OFS=\"-\"}{print $1,$3,$5}\'  /etc/passwd | head -3   #按照数据库:分隔打印第1,3,5列,指定-分隔root-0-rootbin-1-bindaemon-2-daemon[root@localhost test20210812]# seq 1 3 >num;cat num  #构造数据123[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,其他/100100.20.3

2)for循环语句

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

3)while循环语句

[root@localhost test20210813]# cat num2  #构造数据60 50 100150 30 1070 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 100150 30 1070 100 40[root@localhost test20210813]# awk \'{sum=0;i=1;do{sum+=$i;i++}while(i<4)print sum}\' num2  #每行累加210190210

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

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

四、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 100150 30 1070 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 0b 3c 1a 5b 2c 3d 7a 1[root@localhost test20210813]# awk \'{print $0}\' num3 | awk \'{h[$1]++}END{for(i in h)print i,h[i]}\'  #去重统计次数a 3b 2c 2d 1

6、去重并求和

[root@localhost test20210813]# cat num3  #测试数据a 0b 3c 1a 5b 2c 3d 7a 1[root@localhost test20210813]# awk \'{print $0}\' num3 | awk \'{h[$1]=h[$1]+$2}END{for(i in h)print i,h[i]}\'  #去重求和a 6b 5c 4d 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  #测试数据11111222244445555[root@localhost test20210813]# cat file2  #测试数据21111333344445555[root@localhost test20210813]# awk \'NR==FNR{a[$0]++} NR>FNR&&a[$0]\' file1 file2 > same.txt  #记录文件相同的行[root@localhost test20210813]# cat same.txt111144445555

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

[root@localhost test20210813]# cat file1  #测试数据11111222244445555[root@localhost test20210813]# cat file2  #测试数据21111333344445555[root@localhost test20210813]# awk \'NR==FNR{a[$0]++} NR>FNR&&!a[$0]\'  file1 file2 > lack.txt  #记录文件1在文件2没有的值[root@localhost test20210813]# cat lack.txt3333
赞(0) 打赏
未经允许不得转载:爱站程序员基地 » shell脚本(16)-awk命令