【Linux笔记】一起入门Linux咯 | 文本处理awk命令

一起入门Linux咯 | 文本处理awk命令


如果觉得对你有帮助,能否点个赞或关个注,以示鼓励笔者呢?!博客目录 | 先点这里

  • 前提概念
    • 什么是awk?
    • awk的工作模式
    • 注意事项
  • awk命令讲解
    • awk的选项
    • awk的内置变量
    • awk格式化输出printf
    • awk模式匹配
    • awk动作中表达式用法
    • awk动作中的条件及循环语句
    • awk的字符串函数
    • awk的数组
  • awk命令实践
    • 修改默认字段分割符,输入输出
    • printf格式化输出
    • 格式化输出top的信息
    • 输出每个学生的平均成绩

前提概念


什么是awk?
  • awk在linux中是一个很重要的文本处理工具,也是一个重要的报告生成器,可以对我们提供的数据进行复杂的处理,并生成我们需要的数据报告格式,所以也称为数据报告生成器
  • 也因为awk可以生成我们自定义的各种格式,所以有时候也称awk是一门编程,因为awk中,可以执行条件判断语句,循环语句,声明变量等各种操作

awk的工作模式

awk的工作模式其实就类似sed一样,逐行处理行数据

语法格式

  • 第一种
    stdout | awk [option] 'BEGIN{}pattern{comands}END{}',通过管道对标准输出进行处理
  • 第二种
    awk [option] 'BEGIN{}pattern{comands}END{}' files , 对文件进行处理

重要概念

BEGIN中的命令是在遍历文件前执行的,END中的命令是在处理文件所有数据后才执行的,pattern中的命令就是对每个匹配行进行处理

  • BEGIN{}
    正式处理数据之前执行
  • pattern
    模式匹配
  • {commands}
    对匹配行进行command命令处理,可以写多个命令,甚至写条件判断语句,循环语句等
  • END{}
    处理完所有匹配行数据后执行
akw注意事项
  • {}中引用变量,不需要加$符号,比如'{print NF}'
  • 总之awk的’'中的内容,如果有字符串,建议使用""双引号括起来,避免被以为是变量
  • akw可以跟多个文件,既处理多个文件

awk命令讲解


awk的选项
  • -F fs
    fs为输入分隔符,fs可以是字符串或正则表达式, 比如awk -F "-" '{print $0}' file
  • -v var=value
    赋值一个用户定义变量,将外部变量传递给awk
  • -f scripfile
    从脚本文件中读取awk命令

awk的内置变量
内置变量含义备注
$0整行内容
$1-$n当前行的第1-n个字段比如hello world,$1是hello, $2是world
NF当前行的字段个数,也就是有多少列Number Field
NR当前行的行号,从1开始计数Number Row
FNR多文件处理时,每个文件行号单独计数,都是从0开始File Number Row
FS输入字段分隔符,不指定就默认以空格或tab键分割输入给awk的内容以FS作为在字段分隔
RS输入行分隔符,默认回车换行
OFS输出字段分割符,默认为空格awk输出的内容的字段以OFS作为字符分割
ORS输出行分割符,默认为回车换行
FILENAME输入行分隔符,默认回车换行
ARGC命令行参数个数awk ‘BEGIN{print ARGC}’ cpu 输出2个参数,awk是一个,cpu文件名也是一个
ARGV命令行参数数组
  • 所谓字段,因为awk默认的字段是分割是空格或tab,既一行数据中,以空格或tab键分割的字符串,awk认为是单独的字段,既单词。就像Java的string.spilt(" ")一样
  • {}中的命令,以;分隔不同的命令
  • pattern默认为Null时,代表匹配所有行,{commands}默认为空是,输出行的完整信息,等价print $0
  • awk的pattern不同于sed的方式操作行号,而是根据NR变量去控制行号,同时pattern不仅局限于使用正则,同时支持运算符号判断,比如大于,小于,等于,不等于等…

awk格式化输出printf
  • printf和print的很大的区别是,print会默认换行,而printf不会做任何事情
格式符含义备注
%s打印字符串printf "%20s" helloworld 右对齐20字符固长输出
%d打印十进制数
%f打印浮点数printf "%0.3f" 123
%x打印十六进制数printf "%#x" 123(输出带0x),printf "%x" 123
%o打印八进制数
%e打印科学计数法
%c打印字符的ASCII码
-左对齐printf "%-20s" hello 左对齐,20固长的字符串输出
+右对齐printf默认输出是右对齐
#打印字符的ASCII码

awk模式匹配

awk模式匹配有两种用法。第一种是RegExp, 按照正则表达式匹配;第二种是关系运算,按照关系运算匹配

RegExp

  • 这个就没有什么好说的,跟sed差不多,不过经过测试awk的pattern不支持行号
  • /root/
    查看含有root字符串的行
  • /root/,/10/
    匹配带有root到10字符串的行数据,范围匹配

关系运算

  • <,>,<=,>=,==,!=
    小于,大于,小于等于,大于当于,相等,不等
    比如,匹配某文件中行数据第3个字段小于50的行, awk '$3<50{print $0}'
    比如,匹配某文件中行数据第7个字段为hello的行, awk '$7=="hello"{print $0}'
    比如,匹配某文件中行号为10的行,awk 'NR==10'{print $0} file.txt
  • ~,!~
    匹配正则表达式,不匹配正则表达式
    比如,匹配某文件中行数据的第3个字段是3位以上数字的行,awk '$3~/[0-9]{3,}{print $0}/'
  • ||&&!
    或,与,非
    比如,匹配某文件中行数据包含java或python的行, awk '/java/||/python/{print $0}'
    比如,匹配某文件中行数据第3列大于50且第8列小于100的行,awk '$3>50 || $8<100{print $0}'

awk动作中表达式用法
格式符含义备注
+
-
*
/
%
^或**乘方
++x就是语言中的i++
x++就是语言中的i++
  • 什么是awk动作,其实就是’BEGIN{}pattern{}END{}'中{}的代码。比如说BEGIN{num = 1;num++;} {num++;}END{print num} , BEGIN代码块初始化num变量,{commands}每匹配一个行,num++, 匹配文件结束后执行END代码块的print num, 输出num变量,这样我们就知道了awk总共匹配了多少行

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

条件语句

  • 这一点其实跟我们平时的c语言是差不多的
if(条件){
	...
} else if (条件){
	...
} else {
	...
}

循环语句

  • while循环
while(条件表达式){
	...
}
  • do while循环
do{
	...
}while(条件表达式)
  • for循环
for(i = 0; i<10;i++){
	...
}

跟c的区别就是,awk的变量不需要声明


awk的字符串函数
函数名解释函数返回值备注
length(str)计算字符串长度整数长度值
index(str1,str2)在str1中查找str2的位置返回值为位置索引,从1开始计数
tolower(str)字符串全部转为小写小写字符串
toupper(str)字符串全部转为大写大写字符串
substr(str,m,n)从str的m个字符开始,窃取n位字符串子串
split(str,arr,fs)按照fs分割字符串,保存到arr数组中数组的长度
match(str,RE)在str中按照RE查找,返回位置索引位置
sub(RE,RepStr,str)从str搜索符合RE的子串,将其替换成RepStr, 替换一个替换个数
gsub(str,arr,fs)从str搜索符合RE的子串,将其替换成RepStr, 替换全部替换个数RE是正则
  • 查找str字符串中"love"子串的位置
    awk 'BEGIN{str="I love you"; index=index(str,"love");print index}'
    awk 'BEGIN{str="I love you"; index=match(str,"love");print index}'


awk的数组

awk的数组的使用和shell脚本中数组的使用是有些不同的,这个要注意

Shell脚本下数组的使用

  • 定义数组
    array=("Jerry" "Tom" "Li" "Allen")
  • 打印元素
    echo ${array[2]}
  • 打印数组元素的个数
    echo ${#array[@]} ,求个数基本都是#xx, 比如字符串的长度#str
  • 打印元素字符的个数
    echo{#array[1]}
  • 给元素赋值
    array[3] = "Mike"
  • 删除元素
    unset array[2], 要删除整个数组则是unset array[@], 其实就是清空遍历
  • 分片访问
    echo ${array[@]:1:3}
  • 元素内容替换
    ${array[@]/old/new}, 使用new替换一个old
    ${array[@]//old/new}, 使用new替换所有old
  • 数组的遍历
for i in array
do
	echo $i
done

awk脚本下数组的使用

  • shell数组的索引下标从0开始,而awk数组索引下标从1开始
  • shell需要通过${array[1]}获取数组元素的值,而awk就跟普通语言一样,array[1]即可

awk命令实践


修改默认字段分割符,输入输出
  • cpu文件 ,大致是top -c输出的内容
# PID,USER,PR,NI,VIRT,RES,SHR,S,%CPU,%MEM,TIME+,COMMAND
165,lwj,20,0,16920,3564,3452,S,0.0,0.0,0:00.30,-bash,
266,lwj,20,0,17016,3656,3344,S,0.0,0.0,0:00.36,-bash,
321,lwj,20,0,27888,6492,3304,S,0.0,0.0,0:00.20,vim,h,
364,lwj,20,0,16884,3444,3372,S,0.0,0.0,0:00.07,-bash,
375,lwj,20,0,14860,1148,964,S,0.0,0.0,0:00.03,sed,-n,/lwj/w,cpua,
  • awk命令:awk 'BEGIN{FS=","}{print $1,$2,$3}' cpu , 修改字段分隔符FS为逗号,,不再是空格或tab键, 输出每行的第1,2,3个单词(要注意,逗号用双引号括住,而不是单引号
165 lwj 20
266 lwj 20
321 lwj 20
364 lwj 20
375 lwj 20
  • awk命令 awk 'BEGIN{FS=",";OFS="-"}{print $0}' cpu, 输入字符分隔修改为",“逗号,输出字符分隔修改为”-",输出每行的第1,2,3个单词(要注意print $1,$2,$3字段之间要用","号分隔,如果没有逗号,使用空格,那么输出分隔符会失效
165-lwj-20
266-lwj-20
321-lwj-20
364-lwj-20
375-lwj-20

printf格式化输出
  • cpu文件 ,大致是top -c输出的内容
# PID,USER,PR,NI,VIRT,RES,SHR,S,%CPU,%MEM,TIME+,COMMAND
165,lwj,20,0,16920,3564,3452,S,0.0,0.0,0:00.30,-bash,
266,lwj,20,0,17016,3656,3344,S,0.0,0.0,0:00.36,-bash,
321,lwj,20,0,27888,6492,3304,S,0.0,0.0,0:00.20,vim,h,
364,lwj,20,0,16884,3444,3372,S,0.0,0.0,0:00.07,-bash,
375,lwj,20,0,14860,1148,964,S,0.0,0.0,0:00.03,sed,-n,/lwj/w,cpua,
  • awk命令:awk 'BEGIN{FS=","}{printf "%-20s %-20s",$1,$2}' cpu 格式化输出cpu的第一和第二列字段,格式化为输出字符串,每一列固定20个字符串,左对齐方式输出,字段之间2个空格长度隔开
165            lwj
266            lwj
321            lwj
364            lwj
375            lwj
  • awk命令:awk 'BEGIN{FS=","}{printf "%+20s %+20s",$1,$2}' cpu, 右对齐
           165                  lwj
           266                  lwj
           321                  lwj
           364                  lwj
           375                  lwj

格式化输出top的信息
  • linux cpu信息,通过top -H -n 1 >> cpu将top的信息追加到cpu文件中
top - 20:42:12 up 40 days,  9:46,  1 user,  load average: 0.00, 0.07, 0.04
Threads: 284 total,   1 running, 245 sleeping,   0 stopped,   0 zombie
%Cpu(s):  1.1 us,  1.0 sy,  0.0 ni, 97.4 id,  0.5 wa,  0.0 hi,  0.0 si,  0.0 st
KiB Mem :  1877536 total,   157380 free,   822956 used,   897200 buff/cache
KiB Swap:        0 total,        0 free,        0 used.   856424 avail Mem

  PID USER      PR  NI    VIRT    RES    SHR S %CPU %MEM     TIME+ COMMAND
 6939 ubuntu    20   0   43556   4076   3296 R  5.9  0.2   0:00.01 top
    1 root      20   0  225520   7796   5204 S  0.0  0.4   1:46.62 systemd
    2 root      20   0       0      0      0 S  0.0  0.0   0:00.20 kthreadd
    4 root       0 -20       0      0      0 I  0.0  0.0   0:00.00 kworker/0:0H
    6 root       0 -20       0      0      0 I  0.0  0.0   0:00.00 mm_percpu_wq
    7 root      20   0       0      0      0 S  0.0  0.0   2:09.87 ksoftirqd/0
    8 root      20   0       0      0      0 I  0.0  0.0  21:46.47 rcu_sched
    9 root      20   0       0      0      0 I  0.0  0.0   0:00.00 rcu_bh
   10 root      rt   0       0      0      0 S  0.0  0.0   0:00.00 migration/0
   11 root      rt   0       0      0      0 S  0.0  0.0   0:06.17 watchdog/0
   12 root      20   0       0      0      0 S  0.0  0.0   0:00.00 cpuhp/0
   13 root      20   0       0      0      0 S  0.0  0.0   0:00.00 kdevtmpfs
   14 root       0 -20       0      0      0 I  0.0  0.0   0:00.00 netns
   15 root      20   0       0      0      0 S  0.0  0.0   0:00.00 rcu_tasks_kthre
   16 root      20   0       0      0      0 S  0.0  0.0   0:00.00 kauditd
   17 root      20   0       0      0      0 S  0.0  0.0   0:01.32 khungtaskd
   18 root      20   0       0      0      0 S  0.0  0.0   0:00.00 oom_reaper
   19 root       0 -20       0      0      0 I  0.0  0.0   0:00.00 writeback
   20 root      20   0       0      0      0 S  0.0  0.0   0:00.00 kcompactd0
   21 root      25   5       0      0      0 S  0.0  0.0   0:00.00 ksmd
   22 root      39  19       0      0      0 S  0.0  0.0   0:12.74 khugepaged
   23 root       0 -20       0      0      0 I  0.0  0.0   0:00.00 crypto
   24 root       0 -20       0      0      0 I  0.0  0.0   0:00.00 kintegrityd
  • awk命令:awk '/PID/,/END/{if (NR>7){printf "%-8s %-8s\n",NR,$0}}' cpu
    我只想要PID以下的所有信息,不包含PID行
    通过/PID/,/END/查询PID行以下的所有信息,因为文本不存在END字符,所以会遍历到文件结束
    通过输出NR,当前行的行号,得到PID行的行号为7,所以通过if条件判断,不输出第7行数据即可
8         9061 ubuntu    20   0   43556   4092   3312 R  6.2  0.2   0:00.01 top                                         
9            1 root      20   0  225520   7796   5204 S  0.0  0.4   1:46.64 systemd                                     
10           2 root      20   0       0      0      0 S  0.0  0.0   0:00.20 kthreadd                                    
11           4 root       0 -20       0      0      0 I  0.0  0.0   0:00.00 kworker/0:0H                                
12           6 root       0 -20       0      0      0 I  0.0  0.0   0:00.00 mm_percpu_wq                                
13           7 root      20   0       0      0      0 S  0.0  0.0   2:09.91 ksoftirqd/0                                 
14           8 root      20   0       0      0      0 I  0.0  0.0  21:46.89 rcu_sched                                   
15           9 root      20   0       0      0      0 I  0.0  0.0   0:00.00 rcu_bh                                      
16          10 root      rt   0       0      0      0 S  0.0  0.0   0:00.00 migration/0                                 
17          11 root      rt   0       0      0      0 S  0.0  0.0   0:06.17 watchdog/0                                  
18          12 root      20   0       0      0      0 S  0.0  0.0   0:00.00 cpuhp/0                                     
19          13 root      20   0       0      0      0 S  0.0  0.0   0:00.00 kdevtmpfs                                   
20          14 root       0 -20       0      0      0 I  0.0  0.0   0:00.00 netns                                       
21          15 root      20   0       0      0      0 S  0.0  0.0   0:00.00 rcu_tasks_kthre                             
22          16 root      20   0       0      0      0 S  0.0  0.0   0:00.00 kauditd                                     
23          17 root      20   0       0      0      0 S  0.0  0.0   0:01.32 khungtaskd                                  
24          18 root      20   0       0      0      0 S  0.0  0.0   0:00.00 oom_reaper                                  
25          19 root       0 -20       0      0      0 I  0.0  0.0   0:00.00 writeback                                   
26          20 root      20   0       0      0      0 S  0.0  0.0   0:00.00 kcompactd0                                  
27          21 root      25   5       0      0      0 S  0.0  0.0   0:00.00 ksmd                                        
28          22 root      39  19       0      0      0 S  0.0  0.0   0:12.74 khugepaged                                  
29          23 root       0 -20       0      0      0 I  0.0  0.0   0:00.00 crypto                                      
30          24 root       0 -20       0      0      0 I  0.0  0.0   0:00.00 kintegrityd

输出每个学生的平均成绩
  • student成绩表
Jerry	80	90	78	56
Tom		45	65	89	12
Allen	89	96	95	87
Li		45	89	75	63
  • awk命令:awk '{total=$2+$3+$4+$5;avg=total/4;printf "%-10s %-10 0.2f\n",$1,avg}' student
    输出每位学生的平均成绩
    total统计每行每个学生的所有成绩,avg求平均分,printf格式化输出,固定10个字符长度,左对齐,浮点数保留小数点后两位
Jerry       76.00
Tom         52.75
Allen       91.75
Li          68.00
  • awk命令:awk '{if($2>60) print $1,$2}' student , 输出第一列成绩中合格的学生(大于60分)
Jerry 80
Allen 89
  • awk命令:awk -f cal.awk student , 计算横向和纵向数据的总和
# cak.awk
BEGIN{
	printf "%-10s%-10s%-10s%-10s%-10s%-10s\n","Name","Chinese","Math","Enligsh","PC","Sum"
}
{
	total=$2+$3+$4+$5;
	for(i=2;i<=NF;i++){
		sum=array[i];
		array[i]=sum+$i;	
	}
	printf "%-10s%-10d%-10d%-10d%-10d%-10d\n",$1,$2,$3,$4,$5,total
}
END{
	printf "%-10s%-10d%-10d%-10d%-10d%-10d\n","",array[2],array[3],array[4],array[5],""
}

# output
Name      Chinese   Math      Enligsh   PC        Sum
Jerry     80        90        78        56        304
Tom       45        65        89        12        211
Allen     89        96        95        87        367
Li        45        89        75        63        272
          259       337       218       0         0

参考资料


  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值