大家好 我是 xindoo,距我上次发技术文章曾经过来快一个半月了,起因是最近的确十分十分的忙,工作日除了吃饭睡觉之外,要么是在工作,要么就是在去工作的路上,而周末的时候我只想
明天 1024 程序猿节,百忙中抽空发篇始终想写良久的文章来凑个冷落,简略教大家如何应用 awk 这个命令行工具。意识我的人都晓得我最早是运维出世,做运维没学会啥太大的本事,有些命令行工具却使得贼溜,awk 就是其中之一。起初我转开发后,凭借精通局部命令行工具的应用疾速解决过很多小问题,命令行的便捷和高效也曾多次震惊到咱们的共事们。
各种命令行工具加管道的组合,能够极快的解决很多问题,这里我就不再开展了,有趣味能够看下我之前写的一篇博客我罕用的一些 linux 命令。而明天的配角是 awk,一款极强的文本处理工具,我日常会用它来做数据荡涤、筛选、查看,甚至实现一些简略的数据统计工作。毫不夸大的说,有些他人须要几个小时、甚至齐全搞不定的工作,我用 awk 分分钟解决完,在他人看来齐全就是黑魔法。
这么说可能你没有感觉,我举个具体的例子。之前有个共事,须要把一个上千万行的文本文件 (大于 500MB) 平均拆成俩文件,其实就是想把千万的用户平均随机拆成两个汇合做一些比照试验,你会怎么搞?实际上我用 awk 一行命令搞定,敲命令 20 秒,执行半分钟。
cat users.txt |awk 'NR%2==0 {print $1}' > 0.txt
cat users.txt |awk 'NR%2==1 {print $1}' > 1.txt
说这么多只是为了引出 awk 的弱小,所以 awk 到底是什么?很多初学者都认为 awk 是一个文本处理工具,它与 grep、sed 同称为 linux 文本三剑客。理论 awk 不仅仅是文本处理工具,它也是 一门编程语言,awk 只是针对于文本处理提供了很多内置变量和函数(稍后会具体介绍),使得他极易用于文本处理而已,接下来请追随我由俭入深来学习下 awk 的应用。
根本应用
awk 的根本用法就是,awk + 具体的执行 + 文本文件,它也能够从 linux 管道里读取内容,两种应用办法如下。
awk program textfile
cat textfile | awk program
awk 实际上是面向行的数据处理的,也就是说它的指令对于每一行数据都会执行一次,比方如下的例子
cat a.txt| awk '{print $1, $3}'
下面这条指令就是输入文件所有行的第 1、3 列,下标是从 1 开始的,而 $0 有非凡含意,指的是这一行的所有数据。awk 缺省是应用空格或者 tab 来辨别列的,有时候文本文件不以空格或者 tab 分列,而是以特殊符号(比方 –)来分列,awk 也提供了 -F 参数来指定分隔符。
cat a.txt| awk -F'-' '{print $1, $3}'
内置变量
awk 极善于解决文本,其中一个起因就是它提供了大量的内置变量,能够很轻易就获取到文本内容的一些信息,比方以后在第几行 (NR)、这一行有多少列(NF),以后解决的文件名(FILENAME) 是啥…… 上面仅列举一部分,
变量 | 作用 |
---|---|
$0 | 以后行的所有内容 |
$1~$n | 以后行的第 1 - 第 n 列 |
NF | 以后行有多少列 |
NR | 以后是第几行,从 1 开始 |
RS | 输出的记录他隔符默 认为换行符 |
OFS | 输入字段分隔符 默认也是空格 |
ORS | 输入的记录分隔符,默认为换行符 |
ARGC | 命令行参数个数 |
ARGV | 命令行参数数组 |
FILENAME | 以后输出文件的名字 |
IGNORECASE | 如果为真,则进行疏忽大小写的匹配 |
ARGIND | 以后被解决文件的 ARGV 标志符 |
比方我要输入一个文本文件 a.txt,以 | 格调的话,第几行别离有多少列,我就能够这么写:
cat a.txt | awk -F'|' '{print NR, NF}'
我在博客《awk 实现类 sql 的 join 操作》中就用到了多个内置变量实现了对多个文本的简单解决,有趣味能够看下,相似的对多个文件求交加、差集都很容易实现。
内置函数
除了内置的变量外,awk 也内置了很多罕用的函数,这里我也不在赘述,具体内容能够查阅 https://www.runoob.com/w3cnote/awk-built-in-functions.html,awk 内置的函数次要分为以下几种:
- 算数函数
- 字符串函数
- 工夫函数
- 位操作函数
- 其它函数
这些内置函数能够实现打大多数罕用的操作,如果这些内置函数还不够用的话,方才也说过了,awk 是一门编程语言,须要啥函数你都能够本人实现。
语法
接下来咱们来介绍下 awk 在命令行外作为一门编程语言的基本知识。
变量
首先从变量开始,除了上文说到的那些内置变量,你也能够自行应用其余的变量。awk 和 python 语言,它是弱类型的,不必申明,变量间接应用。比方要求一个文本文件第 2 列的综合和平均值,就能够这么写。
cat a.txt |awk '{sum += $2; cnt += 1} END {print sum, sum/cnt}'
这里 sum 和cnt就是咱们自定义的变量,随用随写,很是不便。除了简略变量外,awk 也反对一些简单数据结构,比方 map,这里我还是举一个例子,比方咱们领有一批人最近一个月今天的体重记录,咱们想晓得每个人这一个月的均匀体重是多少,数据如下,总共有三列,别离是姓名、日期、体重。
张三 2021-10-01 67.7
李四 2021-10-01 83.9
张三 2021-10-02 68.1
李四 2021-10-02 85.0
张三 2021-10-03 68.3
张三 2021-10-01 67.9
李四 2021-10-03 84.0
...
应用 awk 中的 map,能够将每个人的体重总和 sum 和数量 cnt 别离存储起来,等到所有数据处理完之后对立输入即可,具体代码如下:
cat a.txt|awk '{sum[$1] += $3;cnt[$1] += 1} END {for (key in sum) {print key, sum[key]/cnt[key]}}'
判断
从下面几个例子中,大家也留神到了,有时候不得不应用一些判断条件。比方在最开始的文本拆分的例子中,我是按行号的奇偶将文件拆分成两个,这个时候须要按不同的含号执行不同的逻辑,在 awk 中判断逻辑也很简略。
awk 'expr {statement}' # 只有 expr 为 true 的时候大括号中的 statement 代码块才会执行。
像上文中曾经屡次呈现的 END 就示意只有所有行都解决完后,其前面的代码块才会执行。和 END 对应的还有BEGIN,其所对应的代码是在文件解决开始前执行,所以个别都会做一些文件初始化的工作。其余你自定的判断也都能够通过相似的形式写,另外它也是反对 if else 的,其写法如下:
cat a.txt |awk '{if (NR%2==1) print NR, $1 ; else print NR, $2}' # 如果是奇数行就输入行号和第一列,否则输入行号和第二列
循环
awk 也反对 for 和 while 循环,和 c 语言 for 和 while 循环是一样的,如下:
for (initialisation; condition; increment/decrement)
action
while (condition)
action
这里我用 awk 实现输入 0 -100 之间所有的素数为例,串一下下面说的循环和判断,除了变量定义外,和 C 语言基本一致了。
BEGIN {
i = 2;
while (i < 100) {
isPrime = 1;
for (j = 2; j < i; j++) {if (i % j == 0) {isPrime = 0;}
}
if (isPrime == 1) {print i;}
i += 1;
}
}
如果代码太长,无奈残缺的拼接到命令行后,能够把代码存到文件中,而后用awk -f 调起,比方:
awk -f getPrime.awk
函数
awk 的函数定义也非常简单,和 js 是一毛一样了,具体能够参考 https://www.runoob.com/w3cnote/awk-user-defined-functions.html
function isPrime(n) {for (j = 2; j < n; j++) {if (i % j == 0) {return 0;}
}
return 1;
}
BEGIN {
i = 2;
while (i < 100) {if (isPrime(i)) {print i;}
i += 1;
}
}
像下面的语法学过编程语言的人都不会生疏把,十分的简略。
结语
awk 作为一面语言仿佛十分的小众,和其余成熟编程语言比起来仿佛毫无劣势,但它只专一于文本处理,在文本处理这一畛域却是佼佼者。不过的确也有个景象,当初随着各类分布式文本检索工具的呈现(比方 elastic search),会应用 awk 的人越来越少了,兴许像这类优良的命令行工具将来会逐步被新生代程序猿忘记在历史的长河中……,所以心愿我这篇文章能让 awk 被更多的人理解到。
另外本文只是浅显的介绍了下 awk 的根底性能,但如果你想要精通 awk 还须要自行查阅一些其余的材料,并且伴以大量的分割。明天我也听了会 csdn 1024 线上流动直播,恰好听到一些 top 级的程序猿为一般程序猿提的倡议,其实都是些陈词滥调的内容,情理大家都懂,但大多数人都是流于平庸,外围还是少了实际和积攒。不积跬步无以至千里,不积小流无以成江河。