awk - 数据分析和展示
NAME
gawk - pattern scanning and processing language
模式扫描和处理语言
awk是一个强大的文本分析工具,相对于grep的查找,sed的编辑,awk在其对数据分析并生成报告时,显得尤为强大。简单来说awk就是把文件逐行的读入,以空格为默认分隔符将每行切片,切开的部分再进行各种分析处理。
格式
gawk [options] 'program' FILE ...
program: PATTERN{ACTION STATEMENTS}
语句之间用分号分隔
常用选项
- -F'' :指明输入时用到的字段分隔符,从文件中读取数据时,用什么做分隔符,和内建变量
FS
一个意思 - -v var=value :自定义变量
- -f /path/to/awk_script :将awk调用文件里写好的awk语法进行执行。
表达式
表达式是最简单的语句,大多数其他语句都是由不同类型的表达式组合而成。初等表达式与其他表达式通过运算符组合在一起,形成一个新的表达式。初等表达式是最原始的构造块:它们包括常量、变量、数组引用、函数调用、以及各种内建变量,例如字段的名字。
常量
awk
中只有两种常量:字符串和数值,将一个字符序列用一对双引号包围起琰就创建一个字符串常量。所有的数都用浮点格式存储。
变量
用户定义的,内建的,或字段。用户定义的变量名字由数字,字母与下划线构成,但是名字不能以数字开始。所有的内建变量的名字都是大写字母。
每一个变量都有一个值,这个值可以是字符串或数值,或两者都是。因为变量的类型不需要事先声明,所以awk需要根据上下文环境推断出变量的类型。当需要时,awk可以把字符串转化为数值,或反之。
内建变量
变量 | 意义 | 默认值 |
---|---|---|
ARGC | 命令行参数的个数 | - |
ARGV | 命令行参数数组 | - |
FILENAME | 当前输入文件名 | - |
FNR | 当前输入行的个数 | - |
FS | 控制着输入行的字段分割符 | “ ” |
NF | 记录每行的字段个数 | - |
NR | 到目前为止读到的行的数量 | - |
OFS | 输出字段分割符 | “ ” |
ORS | 输出时的换行符 | "\n" |
RLENGTH | 被函数match匹配的字符串的长度 | - |
RS | 输入时的换行符 | "\n" |
RSTART | 被函数match匹配的字符串的开始 | |
SUBSEP | 下标分割符 | "\034" |
**NF** (number of field)
有时候,必须总是通过\$1,\$2这样的形式引用字段,但是任何表达式都可以出现在\$后面,用来指明一个字段的编号:表达式被求值,求出的值被当作字段的编号。awk计算当前输入行的字段数量,并将它存储在一个内奸的变量中,这个变量叫作`NF`,因此
`{print NF,$1,$NF}`
将会打印:每一行的字段数量,第一个字段,以及最后一个字段
```
[root@node1 ~]# echo "dm ft 12" | awk '{print NF,$1,$NF}'
3 dm 12
[root@node1 ~]# echo "dm ft 12" | awk '{print NF,$1,$NF-1}'
3 dm 11
[root@node1 ~]# echo "dm ft 12" | awk '{print NF,$1,$(NF-1)}'
3 dm ft
```
**NR** (number of record)
`NR`这个变量计算到目前为止,读取到的行的数量。
```
[root@node1 ~]# echo -e "dm ft\nft dm" | awk '{print NR,$0}'
1 dm ft
2 ft dm
```
**FNR**(file record number)
`FNR`表示从当前输入的行数,总共读取的行数。分别在与`NR`的地方是`FNR`对各文件分别计数
```
[root@node2007 ~]# awk -F':' '{print FNR}' /etc/passwd /etc/shadow
1
2
...
20
1
2
...20
[root@node2007 ~]# awk -F':' '{print NR}' /etc/passwd /etc/shadow
1
2
...
40
[root@node1 ~]# awk 'FNR == 1' /etc/passwd
root❌0:0:root:/root:/bin/bash
<br />
**FILENAME**
`FILENAME`表示当前输入文件名
[root@node2007 tmp]# awk 'FILENAME == "/tmp/a.log" {print }' /tmp/*.log
hello
[root@node2007 tmp]# awk '{print FILENAME}' /tmp/a.log /tmp/b.log
/tmp/a.log
/tmp/b.log
<br />
**FS**(input field seperator)
输入字段分割符,默认为空白字符。
[root@node2007 ~]# echo "root:x" | awk -v FS=':' '{print $1}'
root
[root@node2007 ~]# echo "root:x" | awk -F':' '{print $1}'
root
<br />
**OFS**(output field seperator)
输出字段分隔符,默认为空白字符。
[root@node2007 ~]# echo "root:x" | awk -v FS=':' -v OFS="|" '{print $1,$2}'
root|x
<br />
**RS**(input record seperator)
输入时的换行符。默认`\n`
[root@node2007 ~]# echo "Hello World" | awk -v RS=' ' '{print}'
Hello
World
[root@node2007 ~]# echo "Hello World" | awk -v RS='o' '{print}'
Hell
W
rld
<br />
**ORS**(output record seperator)
输出时的换行符。默认`\n`
[root@node2007 ~]# echo "Hello World" | awk -v ORS='\t' '{print}'
Hello World [root@node2007 ~]# echo "Hello World" | awk -v ORS='#' '{print}'
Hello World#[root@node2007 ~]#
<br />
**ARGC**
命令行参数的个数。awk命令本身是第一个参数,也就是数组的零下标,之后的常用选项不算做参数,最后提供的参数也是参数。
**ARGV**
数组,保存的是命令行所给定的各参数
####内建函数
内建函数分为`算术函数`和`字符串函数`个人使用算术函数不多,这里只讲`rand`算术函数,剩余都是字符串函数。
**算术函数:**
**rand()**
返回0和1之间的一个随机数
[root@node2007 ~]# echo | awk '{print rand()*10}' #返回0-10之间的数字
2.37788
<br />
**字符串函数:**
函数|描述
-|-
index(s,t)|返回字符串t在s中第一次出现的位置,如果t没有出现的话,返回0
length(s)|返回s包含的字符个数
split(s,a)|用`FS`将s分割到数组a中,返回字段的个数
split(s,a,fs)|用`fs`分割s到数组a中,返回字段的个数
sub(r,s)|将\$0的最左最长的,能被r匹配的子字符串替换为s,返回替换发生的次数
sub(r,s,t)|t就是选定区域,然后执行`sbu(r,s)`
substr(s,p)|返回s中从位置p开始的后缀
substr(s,p,n)|返回s中从位置p开始的,长度为n的子字符串
gsub(r,s)|将\$0中所有出现的r替换为s,返回替换发生的次数
gsub(r,s,t)|将字符串t中所有出现r替换为s,返回替换发生的次数
<br />
**index**
[root@node2007 ~]# echo -e "hello\nworld"| awk '{print index($1,"o")}'
5
2
[root@node2007 ~]# echo -e "hello\nworld"| awk '{print index($1,"a")}'
0
0
<br />
**length**
[root@node2007 ~]# echo -e "hello\nworldd"| awk '{print length($1)}'
5
6
<br />
**split**
[root@node2007 ~]# echo -e "/etc/nginx/nginx.conf"| awk '{split($0,a,"/");for(i=1;i<=length(a);i++){if (a[i] == ""){countine}else{print a[i]}}}' #语法格式后面会详细介绍
etc
nginx
nginx.conf
<br />
**sub,gsub**
`sub`和`gsub`相当于`sed`命令替换命令后带`g`参数的效果。
匹配指定域/记录中最大、最靠左边的子字符串的正则表达式,并用替换字符串替换这些字符串。如果没有指定目标字符串就默认使用整个记录。替换只发生在第一次匹配的时候。
[root@node2007 ~]# echo -e "hello"| awk '{print $0,sub("l","L"),$0}'
hello 1 heLlo
[root@node2007 ~]# echo -e "hello world"| awk '{print $0,sub(/l+/,"L",$2),$0}'
hello world 1 hello worLd
[root@node2007 ~]# echo -e "hello world"| awk '{gsub(/l+/,"L");print}'
heLo worLd
[root@node2007 ~]# echo -e "hello world"| awk '{gsub(/l+/,"L",$2);print}'
hello worLd
<br />
**substr**
[root@node2007 ~]# echo -e "/etc/nginx/nginx.conf"| awk -v FS='/' '{print substr($NF,1)}' #给定一个位置,然后将后缀输出
nginx.conf
[root@node2007 ~]# echo -e "/etc/nginx/nginx.conf"| awk -v FS='/' '{print substr($NF,1,5)}' #限定输出长度
nginx
<br />
####字段变量
当前输入行的字段从\$1,\$2,一直到\$NF;\$0表示整行。字段变量与其他变量相比没什么不同,也可以用在算术或字符串运算中,也可以被赋值。
[root@node2007 ~]# echo "hello" | awk '{$1 = "world";print}'
world
[root@node2007 ~]# echo "10" | awk '{$1 = $1 / 2;print $1}'
5
<br />
###PATTERN(模式)
####BEGIN&END
`BEGIN`与`END`这两个模式不匹配任何输入行,实际情况是,当awk从输入读取数据之前,`BEGIN`的语句开始执行;当所有输入数据被读取完毕,`END`语句开始执行。于是,`BEGIN`和`END`分别提供了一种控制初始化与扫尾的方式。
`BEGIN`的一个常用用途是更改输入行被分割为字段的默认方式。使用内键变量`FS`和常用选项`-F`
[root@node1 tmp]# cat countries
USSR 8649 275 Asia
Canada 3852 25 North America
China 3705 1032 Asia
USA 3615 237 North America
[root@node1 tmp]# awk 'BEGIN{FS="\t"
printf("%10s%6s%5s %s\n\n",
"country","area","pop","continent")
}
{ printf("%10s %6d %5d %s\n",$1,$2,$3,$4)
area = area + $2
pop = pop + $3
}
END{printf("\n%10s %6d %5d\n","TOTAL",area,pop)}' countries
country area pop continent
USSR 8649 275 Asia
Canada 3852 25 North America
China 3705 1032 Asia
USA 3615 237 North America
TOTAL 19821 1569
<br />
####relational expression
`relational expression{action}`表示每碰到一个使`relational expression`为真的输入行,`{action}`就执行。为真:指的是其值非零或非空。这里的`relational expression`其实就是使用操作符来做判断,并根据判断结果来确定是否要执行`{action}`。
[root@node2007 tmp]# awk -F':' '$3 == 0{print}' /etc/passwd
root❌0:0:root:/root:/bin/bash
* `relational expression`是表达式:
- 比较操作符:`>,<,>=,<=,!=,==,~(匹配),!~(不匹配)`
- 算术操作符:`+,-,*,/,^(指数运算),%`
- 赋值操作符:`=,+=,-=,/=,%=,^=,++,--`
- 模式匹配符:`||,&&,!(使用时最好将所需取反用小括号括起来)`
<br />
####/regular expression/
`/regular expression/{action}`仅处理能够被此处模式匹配到的行。此处的`regular`即可使用`regex`(正则表达式)来做匹配
[root@node2007 tmp]# awk -F':' '$1 ~ /oot>/{print}' /etc/passwd #只要$1包含oot结尾的单词即为真
root❌0:0:root:/root:/bin/bash
[root@node2007 tmp]# awk -F':' '$1 ~ /o*t>/{print $1}' /etc/passwd #这里的的o*
匹配的是零个o或者任意个o,与glob语法中的*
请区分下
root
halt
<br />
####line ranges
`/part1/,/part2/`匹配一个或多个输入行,这些输入行从匹配part1的行开始,到匹配part2的行结束,包括这两行;part1可以与part2匹配到同一行。`part`匹配也可使用正则表达式。
**注:不支持直接给出数字,但可以使用内键变量`FNR`来代替直接给出数字。**
[root@node2007 tmp]# echo -e "1\n2\n1\n3\n2\n3" | awk '/1/,/3/{print}' #这里可以看出只匹配第一个
1
2
1
3
[root@node2007 tmp]# echo -e "1\n2\n1\n3\n2\n3" | awk 'FNR == 3 {print}'
1
[root@node2007 tmp]# echo -e "1\n2\n1\n3\n2\n3" | awk 'FNR <= 3 {print}'
1
2
1
<br />
####模式总结:
模式|例子|匹配
-|-|-
BEGIN|BEGIN|输入被读取之前
END|END|所有输入被读取完之后
expression|$3 < 100|第3个字段小于100的行
string-matching| $2 ~ /Asia/|第2字段含有Asia的行
compound|\$3 < 100 && \$2 ~ /Asia/|第3个字段小于100并且第2字段含有Asia的行
range|NR==10,/^root\>/|第10行到行首第一个单词是root的之间的行。
**额外使用技巧:**
正则表达式可以不用包围在两个斜杠中,可以将正则表达式赋值给一个变量,然后使用该变量匹配数据。
BEGIN { digits = "[1]+$" }
$2 ~ digits
<br />
###流程控制语句
> awk提供有用于决策`if-else`语句,以及循环语句,它们只能用在动作(action)里。所有的这些都来源于C语言,如果你熟悉C语言,我相信下面的语法对你来说小菜一碟。
> awk 提供花括号用于语句组合,`if-else`用于决策,`while`,`for`,`do`语句用于循环。一条单独的语句总是可以被替换为一个被花括号包围起来的语句列表,列表中的语句用换行符或分号分开,换行符可以出现在任何左花括号之后,也可心出现在任何右花括号之前。
流程控制语句:
if (expression) statements
if (expression) statements1 else statements2
while (expression) statements
for (variable in array) statements
do statements while (expression) #执行statements,如果为expression为真就重复
状态控制
break #退出循环
continue #退出当前循环
next #开始输入主循环的下一次迭代,BEGIN后算主循环
exit #执行END动作;如果已经在END动作内,那就退出程序,将expression作为程序退出状态返回
<br />
####if
语法格式:
PATTERN {
if (condition)
{
action
....
}
else
action
}
if-else可以缩写成如下格式:
selector?if-true-expression:if-false-expression
#if-else-if
PATTERN {
if (condition1)
{
action1
}
else if (condition2)
{
action2
}
...
else
action
}
示例:
[root@node2007 ~]# echo "1 2 3" | awk '{if ($1 == 1){print "\$1 equal 1"}}'
$1 equal 1
[root@node2007 ~]# echo "1 2 3" | awk '{if ($1 != 1){print "\$1 equal 1"}else{print "other is 2 3"}}'
other is 2 3
[root@node2007 ~]# echo "1 2 3" | awk '{if ($1 != 1){print "\$1 equal 1"}else if ($2 == 2){print "\$2 equal 2"}}'
$2 equal 2
<br />
####for
C语言的for语句,这里不做解释。
PATTERN {
for (i=1;i<=10;++i){
action
...
}
}
无限循环
PATTERN {
for (;
awk - 数据分析和展示的更多相关文章
- 数据分析与展示——NumPy库入门
这是我学习北京理工大学嵩天老师的<Python数据分析与展示>课程的笔记.嵩老师的课程重点突出.层次分明,在这里特别感谢嵩老师的精彩讲解. NumPy库入门 数据的维度 维度是一组数据的组 ...
- 【学习笔记】PYTHON数据分析与展示(北理工 嵩天)
0 数据分析之前奏 课程主要内容:常用IDE:本课程主要使用:Anaconda Anaconda:一个集合,包括conda.某版本Python.一批第三方库等 -支持近800个第三方库 -适合科学计算 ...
- python数据分析及展示(一)
一.IDE选择 Anaconda软件:开源免费,https://www.anaconda.com下载,根据系统进行安装.由于下载速度慢,可以去清华大学开源软件镜像站下载. Spyder软件设置:Too ...
- 数据分析与展示---Pandas库数据特征分析
说明:0轴axis=0和1轴axis=1 简介 一:数据的排序 二:数据的基本统计分析 三:数据的累积统计分析 四:数据的相关分析 一:数据的排序 a b c d a b c d 二:数据的基本统计分 ...
- 数据分析与展示---Matplotlib基本绘图函数
一:基本绘图函数(这里介绍16个,还有许多其他的) 二:pyplot饼图plt.pie的绘制 三:pyplot直方图plt.hist的绘制 (一)修改第二个参数bins:代表直方图的个数,均分为多段, ...
- pyecharts数据分析及展示
仅仅从网上爬下数据当然是不够用的,主要还得对数据进行分析与展示,大部分人都看重薪资,但是薪资数据有的是*k/月,有的是*万/月,还有*万/年等等,就要对数据进行清理 将所有单位统一化,全部换算成统一单 ...
- Python数据分析与展示(1)-数据分析之表示(1)-NumPy库入门
Numpy库入门 从一个数据到一组数据 维度:一组数据的组织形式 一维数据:由对等关系的有序或无序数据构成,采用线性方式组织. 可用类型:对应列表.数组和集合 不同点: 列表:数据类型可以不同 数组: ...
- 数据分析与展示——Pandas数据特征分析
Pandas数据特征分析 数据的排序 将一组数据通过摘要(有损地提取数据特征的过程)的方式,可以获得基本统计(含排序).分布/累计统计.数据特征(相关性.周期性等).数据挖掘(形成知识). .sort ...
- 数据分析与展示——Matplotlib基础绘图函数示例
Matplotlib库入门 Matplotlib基础绘图函数示例 pyplot基础图表函数概述 函数 说明 plt.plot(x,y,fmt, ...) 绘制一个坐标图 plt.boxplot(dat ...
随机推荐
- Linux】目录文件权限的查看和修改【转】
转载自:http://zhaoyuqiang.blog.51cto.com/6328846/1214718 ============================================== ...
- linux脚本中有source相关命令时的注意事项
写这个问题起因是因为一个同学去的java一键脚本环境变量设置问题, [root@localhost u01]# more 1.sh #!/bin/bash grep -q "export J ...
- java并发编程(九)ThreadLocal & InheritableThreadLocal
参考文档: https://blog.csdn.net/u012834750/article/details/71646700 threadlocal内存泄漏:http://www.importnew ...
- c语言之连接符
c语言之连接符 1.连接符 连接符的概念是结合define预编译指令的使用技巧,用户可以向define中传入字符串来调用不同功能的函数. 2.代码例子 #include <stdio.h> ...
- Java 签名验签工具类
public class SignatureUtil { private static final String CHARSET = "UTF-8"; private static ...
- 014 Vue学习笔记2
1.组件化 在大型应用开发的时候,页面可以划分成很多部分.往往不同的页面,也会有相同的部分.例如可能会有相同的头部导航.但是如果每个页面都独自开发,这无疑增加了我们开发的成本.所以我们会把页面的不同部 ...
- [转帖]UML类图关系图解
UML类图关系图解 https://www.cnblogs.com/TvvT-kevin/p/9357339.html 一.类结构 在类的UML图中,使用长方形描述一个类的主要构成,长方形垂直地分为三 ...
- LOJ2874 JOISC2014 历史研究 分块、莫队
传送门 看到出现次数自然地考虑莫队. 但是发现如果需要删除并动态维护答案的话,则要用一个堆来维护答案,增加了一个\(log\).但是加入操作却没有这个\(log\),所以我们考虑避免删除操作. 分块, ...
- FusionInsight大数据开发---Hive应用开发
Hive应用开发 了解Hive的基本架构原理 掌握JDBC客户端开发流程 了解ODBC客户端的开发流程 了解python客户端的开发流程 了解Hcatalog/webHcat开发接口 掌握Hive开发 ...
- GoF的23种设计模式之创建型模式的特点和分类
创建型模式的主要关注点是“怎样创建对象?”,它的主要特点是“将对象的创建与使用分离”.这样可以降低系统的耦合度,使用者不需要关注对象的创建细节,对象的创建由相关的工厂来完成.就像我们去商场购买商品时, ...