大家好 我是xindoo,距我上次发技术文章曾经过来快一个半月了,起因是最近的确十分十分的忙,工作日除了吃饭睡觉之外,要么是在工作,要么就是在去工作的路上,而周末的时候我只想

明天1024 程序猿节,百忙中抽空发篇始终想写良久的文章来凑个冷落,简略教大家如何应用awk这个命令行工具。意识我的人都晓得我最早是运维出世,做运维没学会啥太大的本事,有些命令行工具却使得贼溜,awk就是其中之一。起初我转开发后,凭借精通局部命令行工具的应用疾速解决过很多小问题,命令行的便捷和高效也曾多次震惊到咱们的共事们。

各种命令行工具加管道的组合,能够极快的解决很多问题,这里我就不再开展了,有趣味能够看下我之前写的一篇博客我罕用的一些linux命令。而明天的配角是awk,一款极强的文本处理工具,我日常会用它来做数据荡涤、筛选、查看,甚至实现一些简略的数据统计工作。毫不夸大的说,有些他人须要几个小时、甚至齐全搞不定的工作,我用awk分分钟解决完,在他人看来齐全就是黑魔法。

这么说可能你没有感觉,我举个具体的例子。之前有个共事,须要把一个上千万行的文本文件(大于500MB)平均拆成俩文件,其实就是想把千万的用户平均随机拆成两个汇合做一些比照试验,你会怎么搞? 实际上我用awk一行命令搞定,敲命令20秒,执行半分钟。

cat users.txt |awk 'NR%2==0 {print $1}' > 0.txtcat 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}'

这里sumcnt就是咱们自定义的变量,随用随写,很是不便。除了简略变量外,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)    actionwhile (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级的程序猿为一般程序猿提的倡议,其实都是些陈词滥调的内容,情理大家都懂,但大多数人都是流于平庸,外围还是少了实际和积攒。不积跬步无以至千里,不积小流无以成江河