linux awk指令详解
声明:一下内容均总结自鸟哥私房菜。
sed是对行进行处理,而awk是对列做处理。看下面这个例子: 将上次登录的用户前三行列出来,只显示用户名和IP
[root@localhost ~]# last | awk '{print $1 "t" $3}' | head -n 3
root 192.168.1.1
root 192.168.1.1
root 192.168.1.1
可以通过awk指令,只将第一列和第三列的内容取出来。awk中默认的分隔符是空格或者tab键,所以有时候取出来的数据类型并不是一致的,可能是你的数据结构有问题。 awk的指令格式通常是这样的:
[root@linux ~]# awk '条件类型 1{动作 1} 条件类型 2{动作 2} ...' filename
其中条件类型可有可无,比如像最上面这个例子,只存在指令不存在条件。注意,awk后续的所有指令都要使用’’单引号扩起来,打印时非变量的部分要使用双引号扩起来。动作必须存放在{}中,变量$1,$2,$3等就表示第一列,第二列,第三列等,而$0比较特殊,它表示一整行。
awk指令执行的顺序是下面这样的: 1. 读入第一行,将第一行存放在$0中,将第一列,第二列等分别存放在,$1, $2…. 等变数当中; 2. 依据 “条件类型” 的限制,判断是否需要进行后面的 “动作”; 3. 做完所有的动作与条件类型; 4. 若还有后续的『行』的数据,则重复上面 1~3 的步骤,直到所有的数据都读完为止。
awk中一些内建变量
变量名称 |
代表含义 |
---|---|
NF |
每一行 ($0) 拥有的字段总数 |
NR |
目前 awk 所处理的是『第几行』数据 |
FS |
目前的分隔字符,预设是空格键 |
例1:获取目前所处理的行数和该行的字段数量
[root@localhost ~]# last | awk '{print $1"t lines: " NR "t columns: " NF}'
例2:读取/etc/passwd中的内容,当第三列的值小于10时打印出来
[root@localhost ~]# cat /etc/passwd | awk '{FS=":"} $3<10 {print $1 "t" $3}'
root:x:0:0:root:/root:/bin/bash
bin 1
daemon 2
adm 3
lp 4
sync 5
shutdown 6
halt 7
mail 8
在这个例子中,先使用cat /etc/passwd读取文件内容,在作为管道流送到下个指令awk ‘{FS=”:”} $3<10 {print $1 “t” $3}’处理,在该指令中第一个动作{FS=”:”}将分隔符设置成”:”号,设置判断条件$3<10,如果第三列的值小于10,则执行动作{print $1 “t” $3},将第一列和第三列的值输出来。但是,可以看到第一行没有正确显示出来,因为在读入第一行的时候,这些变数还是按照预设的空格作为分隔符的。那么怎么再读入第一行时就修改这个预设的分隔符呢?可以使用BEGIN。如下所示:
[root@localhost ~]# cat /etc/passwd | awk 'BEGIN {FS=":"} $3<10 {print $1 "t" $3}'
root 0
bin 1
daemon 2
adm 3
lp 4
sync 5
shutdown 6
halt 7
mail 8
例3:薪资计算功能 创建一张pay.txt文件,文件中输入内容如下: Name 1st 2nd 3th VBird 23000 24000 25000 DMTsai 21000 20000 23000 Bird2 43000 42000 41000 计算每个人的工资总额,并按格式化输出
[root@localhost ~]# cat pay.txt | awk 'NR==1{printf "%10s %10s %10s %10s %10sn",$1,$2,$3,$4,"total"}
NR>=2{total=$2+$3+$4;printf"%10s %10d %10d %10d %10.2fn",$1,$2,$3,$4,total}'
Name 1st 2nd 3th total
VBird 23000 24000 25000 72000.00
DMTsai 21000 20000 23000 64000.00
Bird2 43000 42000 41000 126000.00
上面这个指令有几点要说明: 所有的动作,即在{}内的指令,如果存在多个指令,则每个指令建要用”;”来分隔或者按回车来分隔,否则会报错。与bash shell变量不一样,在awk中定义的变量可以直接使用。此外,awk的指令中支持使用if表达式,上面的指令也可以改成下面这样:
[root@localhost ~]# cat pay.txt | awk '{if(NR==1) printf "%10s %10s %10s %10s %10sn",$1,$2,$3,$4,"total"} NR>=2{total=$2+$3+$4;printf "%10s %10d %10d %10d %10.2fn",$1,$2,$3,$4,total}'
Name 1st 2nd 3th total
VBird 23000 24000 25000 72000.00
DMTsai 21000 20000 23000 64000.00
Bird2 43000 42000 41000 126000.00
例4:高级特性,for循环 新建一个reg.dat文件,在文件中输入内容: Mary O.S. Arch. Discrete Steve D.S. Algorithm Arch. Wang Discrete Graphics O.S. Lisa Graphics A.I. Lily Discrete Algorithm 第一行,表示学生名字,二三四行分别表示该学生所选择的课程,下面使用awk结合for循环以及阵列来统计每门课程的选课人数。
[root@localhost ~]# cat reg.dat | awk '{for(i=2;i<=NF;i++) Number[$i]++} END {for(course in Number) printf("%10s %1dn",course,Number[course])}'
O.S. 1
Class1 1
Class2 1
Algorithm 1
D.S. 1
Graphics 2
Discrete 2
Arch. 1
Awk指令中第一个动作是{for(i=2;i<=NF;i++) Number[$i]++},该动作会将课程名称作为index,统计出每节课程所选人数作为相应的值。要注意,在linux中使用一个数组类型不需要声明,所以在上面这个动作中直接就开始使用Number这个数组了,而$i会将一列中的值全部取出来,作为number的index,然后再取出number[index]值做++操作,所以最后得到的number是以课程名称为index,课程的选课人数为value的数组。END表示必须等到所有的值全部遍历完才执行下面的动作。而第二个动作{for(course in Number) printf(“%10s %1dn”,course,Number[course])}则是遍历该数组number,并将结果输出来。这些都是awk的高级特性,详细可以参考http://linux.vbird.org/linux_basic/0330regularex/awk.pdf
- oracle的TAF浅析 (r6笔记第37天)
- R语言高级绘图命令(标题-颜色等)
- 14(02)正则表达式,Pattern,Mactcher,Math,BigInteger,BigDeximal,System等
- R语言 判别分析
- Apache、struts1、struts2文件上传下载的3种方式
- 解析实时的DB time过程分析(r6笔记第35天)
- sql嵌入html格式显示报表(r6笔记第34天)
- hive计算日期差函数datediff,hive修改日期连接符
- 深度学习界的 “吃鸡挂”——目标检测 SSD 实验
- Hadoop查看所有JOB以及如何Kill指定用户的所有Job
- Java基础-23(01)总结多线程,线程实现Runnable接口,线程名字获取和设置,线程控制,线程安全,同步线程
- ORA-01427问题的分析和解决(r6笔记第51天)
- 从编程实现角度学习 Faster R-CNN(附极简实现)
- Java基础-23(02)总结多线程,线程实现Runnable接口,线程名字获取和设置,线程控制,线程安全,同步线程
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- django实战(五)--增加数据
- 实战django(一)--(你也能看懂的)注册与登录(带前端模板)
- 【python-leetcode23-多路归并】合并k个排序链表
- 实战django(二)--登录实现记住我
- org.apache.ibatis.binding.BindingException: Invalid bound statement (not found): com.gong.mybatis.da
- 【python-leetcode378-二分查找】有序矩阵中的第k小元素
- 使用cookie来记录用户登录次数,为何次数不更新
- (二)golang--windows下vscode的安装以及go环境的配置
- mybatis文件映射之使用#取值时的一些规则
- 【论文笔记】Improved Residual Networks for Image and Video Recognition(ResNet新变体:IResNet)
- SQL语句在MYSQL中的运行过程和各个组件的介绍
- (五)golang--常用的一些玩意
- 关于MYSQL 的日志系统
- (六)golang--变量
- springmvc之文件上传