Awk:`开始{`第一部分

2020-10-30 19:31:28

前几天,我正在看Bryan Cantrill的2018年演讲、铁锈和其他有趣的事情,他在讨论不同编程语言和社区的价值时发表了随意的评论。他说,“如果你拿到AWK编程语言手册…。大约两个小时后你会读完,然后你就完成了。就这样。你知道awk的一切。“。

我之前在各处都使用过awk的片段。其中大多数是在谷歌搜索利基数据文件操作时由Stack Overflow Answers给我的。但是,我没有足够的知识从头开始成功地编写一个awk程序。我绝对没有真正掌握这门语言,也没有真正掌握它的力量。而且,花几个小时来学习布莱恩·坎特里尔(Bryan Cantrill)所说的他一天使用三次的语言,听起来似乎是一个相对较小的时间投资。

原来,学习awk需要两个多小时,而我绝不是专家…。然而(增长心态!)。但是,我现在知道的足够多了,可以写一些关于要点的东西了。开始了!

AWK对于数据文件操作非常有用。我只用了几天,我希望我能投入时间早点学习它。遇到数据文件时,我通常的工作流程是将其导入Google Sheet并使用其内置函数。如果这些还不够,我会编写一些代码片断来获得我想要的信息。AWK比我以前做的要强大得多。我们来看一下,

如果我们要学习awk,我们需要知道如何运行awk程序。在shell中运行awk程序的语法为:

我们还可以编写更长的awk程序来运行,而不是内联编写awk代码。我们可以使用awk代码编写文件,然后使用-f<;awk-program-filename>;内联传递给awk。

嗯,什么是AWK计划?我们知道它最适合用于简单的数据重新格式化或操作。它的方法是对数据文件中的不同模式执行不同的操作。Awk程序的基本语法取决于这些模式和操作。

我们可以给出任意多个图案{action}对。每一对都将独立于其他对执行。这意味着如果一行匹配多个模式,则它将有多个相应的操作。在上面的示例中,我们使用换行符来分隔不同的对。与bash类似,我们还可以使用;来分隔命令并将所有内容放在一行中:pattern{action};pattern{action}

但是,事实证明awk更有用(也更有趣!)。使用数据文件。联合国有一些公开可用的数据集。我选择了这一条有关小学、中学和大专教育的问题,首先进行深入研究。

让我们从使用awk开始了解数据的外观。NR是一个预定义变量,它记录到目前为止在文件中读取的行数。我们可以使用它来查看程序的前几行。在本例中,我们的模式将是NR<;=5,并且通过不包括动作,隐含的动作将被打印:

$awk';NR<;=5';Education ation.csvT07,&34;小学、中学和高等教育水平的入学人数";,地区/国家/地区,年份,系列,价值,脚注,来源1,#34;合计,所有国家或地区,2005,小学注册学生(千人),";678,991.6070";,";联合国教育、科学及文化组织(教科文组织),蒙特利尔,教科文组织统计研究所统计数据库,上次访问时间为2019年3月。合计,所有国家或地区,2005年,毛入学率-小学(男),104.9360,&34;联合国教育、科学及文化组织(教科文组织),蒙特利尔,教科文组织统计研究所统计数据库,上次访问时间为2019年3月。";1,#34;合计,所有国家或地区";2005年,毛入学率--小学(女),99.9214,";联合国教育、科学及文化组织(教科文组织)蒙特利尔,教科文组织统计研究所统计数据库,最后一次进入2019年3月。";

好的,看起来这给了我们一些关于我们档案的信息。值得注意的是:

有两个标题行:标题行和告诉我们字段是什么的行。

…。除非有时双引号字符串中有逗号:";合计,所有国家或地区";

我们可以使用漂亮的向前移动NR忽略前两个标题行。我们可以匹配NR>;2的模式。注意:AWK是1索引的。

AWK的默认字段分隔符是空格。我们实际上可以通过打印第一个字段来看到这一点。要访问字段的值,我们使用$<;field_index>;。因此,$1是第一个字段,$2是第二个字段,依此类推。$0指的是整行。

我们可以确认我们是在空位上分开。AWK可以选择使用-F';分隔符标志指定不同的字段分隔符:

太棒了!但是…。。我们在带有双引号的字符串中嵌入了逗号。果然,如果我们打印第二个字段($2),我们会看到:

嗯哼。我们这里想要的是按内容拆分字段。这是awk没有的,但是gawk(GNU Awk)有:FPAT!从Gawk手册中可以看到:“所有正确编写的awk程序都应该与Gawk一起工作。因此,在大多数情况下,我们不会区分Gawk和其他awk实现。

听起来我们可以在这里用呆瓜代替。让我们试试模式匹配。我不打算在这里介绍正则表达式,但是我们想要的模式(由";[^,]*|\";[^\";]+\";";]+\";";定义)是以非逗号字符开头,或者以双引号开头,只包含非引号字符,以双引号结束的任何模式:

$gawk';BEGIN{FPAT=";[^,]*|\";[^\";]+\";}NR<;=5{print$2}';Education ation.csv";小学、中学和高等教育水平的入学人数总数,所有国家或地区总数#34;";总数,所有国家或地区总数";";总数,所有国家或地区总数";";总计,所有国家或地区总数";";总计,所有国家或地区总数";";总计,所有国家或地区总数";";总计,所有国家或地区总数";";总计,所有国家或地区总数";

我在没有解释的情况下偷偷地把一个开始放进去。让我们来个简短的切线…。

除了模式和操作之外,awk还具有BEGIN和END块的概念。在处理任何数据之前执行BEGIN。它对于声明变量或打印要显示在开头的文本非常有用。类似地,在处理数据之后执行END。它对于对数据聚合执行操作非常有用,例如求和的平均值。

这意味着如果我们想写一些“Hello,awk!”程序,我们甚至不需要数据文件就可以做到这一点。

…。回到我们的示例。在我们的示例中,我们使用BEGIN块在读取数据文件之前声明FPAT。

但是,我们只看了前5行。据我们所知,文件的其余部分可能看起来完全不同。让我们再次使用NR查看文件的更多内容。首先,让我们计算出文件有多长。我们可以用这里的最后一块。在解析完整个文件之后,我们可以看到NR的值是什么,这将告诉我们它有多少行:

好的,也许如果我们每500行打印一次,我们就会对我们正在查看的数据有所了解。我们可以将我们的模式设置为仅当NR为500的倍数时:

…。我要把这篇博文放在一个真正的悬崖衣架上。主要是因为感觉已经太久了!还有另一篇关于awk的帖子,内容是实际查看数据并对其进行操纵,以找出哪些国家在接受教育的男性和女性数量上存在明显差异。