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 ...
随机推荐
- 二分类问题F-score评判指标(转载)
分类模型的评价指标Fscore 小书匠深度学习 分类方法常用的评估模型好坏的方法. 0.预设问题 假设我现在有一个二分类任务,是分析100封邮件是否是垃圾邮件,其中不是垃圾邮件有65封,是垃圾邮件有3 ...
- 分布式文件系统HDFS
利用Shell命令与HDFS进行交互 以”./bin/dfs dfs”开头的Shell命令方式 1.目录操作 在HDFS中为hadoop用户创建一个用户目录(hadoop用户) 启动hadoop 创建 ...
- 微软SQL Server 2019 全新发布,更新内容亮点都在这里了
IT之家11月7日消息 在Microsoft Ignite 2019 大会上,微软正式发布了新一代数据库产品SQL Server 2019.使用统一的数据平台实现业务转型SQL Server 20 ...
- 请教网友:#pragma pack(push) #pragma pack(pop)无效
//try 一 try #pragma back(push) #pragma pack(2) struct E { char a; short b; double c; float d; char e ...
- Python(三)对装饰器的理解
装饰器是 Python 的一个重要部分,也是比较难理解和使用好的部分.下面对装饰器做一下简单整理 1. 前言 装饰器实际上是应用了设计模式里,装饰器模式的思想: 在不概念原有结构的情况下,添加新的功能 ...
- [原创]小巧免杀的端口转发工具PortTran(附.net源码)
0x001 简介 PortTran by k8gege.NET版端口转发工具,支持任意权限下转发 0x002 背景工具在2016年左右写的,当时某个内网不知何原故LCX用不了 由于Win2003才刚停 ...
- TeamViewer 一款远程控制软件
TeamViewer 一款远程控制软件,可以在任何防火圈和Nat代理的后台用于远程控制的应用程序. 主要功能:桌面共享和文件传输. 使用前提:两台计算机上同时运行TeamViewer, 使用方法:如果 ...
- 【chromium】cef是如何进行版本控制的?
搜了搜cef相关的文章,内容大多是 如何下载源码,如何编译,还有一些源码剖析,但是很少有人说明对cef进行开发时如何保存修改,使用git进行修改后的版本控制. cef是怎么做的? cef源码分为两个部 ...
- Golang读取并修改非主流配置文件
今天工作中碰到的问题,要求修改此配置文件,没看出来是什么格式,用了下面的思路: mysql { # If any of the files below are set, TLS encryption ...
- Java学习:泛型简介
泛型 泛型:是一种未知的数据类型,当我们不知道使用什么数据类型的时候,可以使用泛型 泛型也可以看出是一个变量,用来接受数据类型 E e : Element 元素 T t : Type 类型 Array ...