博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
awk教程_通过两个简单的教程来提高awk技能
阅读量:2528 次
发布时间:2019-05-11

本文共 5630 字,大约阅读时间需要 18 分钟。

awk教程

Awk是Unix和Linux用户工具箱中最古老的工具之一。 awk由Alfred Aho,Peter Weinberger和Brian Kernighan(该工具名称的A,W和K)于1970年代创建,它是为复杂的文本流处理而创建的。 它是sed的一个附带工具,即流编辑器,用于逐行处理文本文件。 Awk允许使用更复杂的结构化程序,并且是一种完整的编程语言。

本文将说明如何将awk用于更结构化和更复杂的任务,包括一个简单的邮件合并应用程序。

AWK程序结构

awk脚本由被{} (花括号)包围的功能块组成。 有两个特殊功能块BEGINEND ,它们在处理输入流的第一行之前和最后一行处理之后执行。 在其间,块具有以下格式:

pattern { action statements }

当输入缓冲区中的行与模式匹配时,将执行每个块。 如果不包括任何模式,则功能块将在输入流的每一行上执行。

同样,以下语法可用于在awk中定义可从任何块调用的函数:

function name(parameter list) { statements }

模式匹配块和功能的这种组合使开发人员可以构建awk程序,以实现重用和可读性。

awk如何处理文本流

Awk从其输入文件中读取文本,或一次流送一行,并使用字段分隔符将其解析为多个字段。 用awk术语来说,当前缓冲区是一个记录 。 有许多特殊变量会影响awk读取和处理文件的方式:

  • FS (字段分隔符):默认情况下,这是任何空格(空格或制表符)
  • RS (记录分隔符):默认情况下,换行符( \ n
  • NF (字段数):awk解析一行时,此变量设置为已解析的字段数
  • $ 0:当前记录
  • $ 1,$ 2,$ 3等:当前记录中的第一,第二,第三等字段
  • NR (记录数):到目前为止,awk脚本已解析的记录数

还有许多其他因素会影响awk的行为,但这足以开始。

AWK单线

对于如此强大的工具,有趣的是,awk的大多数用法都是基本的单行代码。 也许最常见的awk程序从CSV文件,日志文件等输入行中打印选定的字段。例如,以下单行代码从/ etc / passwd打印用户名列表:

awk -F":" '{print $1 }' /etc/passwd

如上所述, $ 1是当前记录中的第一个字段。 -F选项将FS变量设置为字符

也可以在BEGIN功能块中设置字段分隔符:

awk 'BEGIN { FS=":" } {print $1 }' /etc/passwd

在以下示例中,可以通过在块之前添加模式匹配来打印其外壳不是/ sbin / nologin的每个用户:

awk 'BEGIN { FS=":" } ! /\/sbin\/nologin/ {print $1 }' /etc/passwd

高级awk:邮件合并

既然您已经掌握了一些基础知识,请尝试使用更结构化的示例更深入地研究awk:创建邮件合并。

邮件合并使用两个文件,一个文件(在本示例中称为email_template.txt )包含要发送的电子邮件的模板:

From: Program committee 
To: {firstname} {lastname} <{email}>
Subject: Your presentation proposal
Dear {firstname},
Thank you for your presentation proposal:
  {title}
We are pleased to inform you that your proposal has been successful! We
will contact you shortly with further information about the event
schedule.
Thank you,
The Program Committee

另一个是CSV文件(称为proposal.csv ),其中包含您要将电子邮件发送给的人:

firstname,lastname,email,title     
Harry,Potter,hpotter@hogwarts.edu,"Defeating your nemesis in 3 easy steps"
Jack,Reacher,reacher@covert.mil,"Hand-to-hand combat for beginners"
Mickey,Mouse,mmouse@disney.com,"Surviving public speaking with a squeaky voice"
Santa,Claus,sclaus@northpole.org,"Efficient list-making"

您要读取CSV文件,替换第一个文件中的相关字段(跳过第一行),然后将结果写入一个名为acceptingN.txt的文件中,为您解析的每一行增加N。

将awk程序写入名为mail_merge.awk的文件中。 语句用;隔开 在awk脚本中。 第一个任务是设置字段分隔符变量和脚本需要的其他两个变量。 您还需要读取并丢弃CSV中的第一行,否则将创建一个以Dear firstname开头的文件。 为此,请使用特殊功能getline,并在读取记录计数器后将其重置为0。

BEGIN {     
  FS=",";
  template="email_template.txt";
  output="acceptance";
  getline;
  NR=0;
}

主要功能非常简单:为处理的每一行,都为各个字段设置了一个变量-firstnamelastnameemailtitle 。 逐行读取模板文件,并且使用function sub来用相关变量的值替换特殊字符序列的任何出现。 然后,将进行任何替换的行输出到输出文件。

由于您要处理的是模板文件和每行一个不同的输出文件,因此您需要在处理下一条记录之前清理并关闭这些文件的文件句柄。

{     
        # Read relevant fields from input file
        firstname=$1;
        lastname=$2;
        email=$3;
        title=$4;
        # Set output filename
        outfile=(output NR ".txt");
        # Read a line from template, replace special fields, and
        # print result to output file
        while ( (getline ln < template) > 0 )
        {
                sub(/{firstname}/,firstname,ln);
                sub(/{lastname}/,lastname,ln);
                sub(/{email}/,email,ln);
                sub(/{title}/,title,ln);
                print(ln) > outfile;
        }
        # Close template and output file in advance of next record
        close(outfile);
        close(template);
}

你完成了! 使用以下命令在命令行上运行脚本:

awk -f mail_merge.awk proposals.csv

要么

awk -f mail_merge.awk < proposals.csv

您会在当前目录中找到生成的文本文件。

高级awk:单词频率计数

awk中最强大的功能之一是关联数组。 在大多数编程语言中,数组项通常由数字索引,但在awk中,数组由键字符串引用。 您可以存储上一节中的proposal.txt文件中的条目。 例如,在单个关联数组中,如下所示:

        proposer["firstname"]=$1;     
        proposer["lastname"]=$2;
        proposer["email"]=$3;
        proposer["title"]=$4;

这使得文本处理非常容易。 一个使用此概念的简单程序就是字频率计数器。 您可以解析文件,在每行中分解单词(忽略标点符号),增加该行中每个单词的计数器,然后输出文本中出现的前20个单词。

首先,在名为wordcount.awk的文件中,将字段分隔符设置为包含空格和标点符号的正则表达式:

BEGIN {     
        # ignore 1 or more consecutive occurrences of the characters
        # in the character group below
        FS="[ .,:;()<>{}@!\"'\t]+";
}

接下来,主循环函数将遍历每个字段,忽略任何空字段(如果在行尾出现标点符号,则会发生此情况),并增加行中单词的单词计数。

{     
        for (i = 1; i <= NF; i++) {
                if ($i != "") {
                        words[$i]++;
                }
        }
}

最后,在处理完文本之后,使用END函数打印数组的内容,然后使用awk的将输出管道输送到shell命令中的功能进行数字排序并打印20个最常见的单词:

END {     
        sort_head = "sort -k2 -nr | head -n 20";
        for (word in words) {
                printf "%s\t%d\n", word, words[word] | sort_head;
        }
        close (sort_head);
}

在本文的早期草稿上运行此脚本将产生以下输出:

[dneary@dhcp-49-32.bos.redhat.com]$ awk -f wordcount.awk < awk_article.txt      
the     79
awk     41
a       39
and     33
of      32
in      27
to      26
is      25
line    23
for     23
will    22
file    21
we      16
We      15
with    12
which   12
by      12
this    11
output  11
function        11

下一步是什么?

由Dale Dougherty和Arnold Robbins撰写。

在awk编程中取得进展的关键之一就是掌握“扩展正则表达式”。 Awk为您可能已经熟悉的sed 语法提供了一些强大的补充。

学习awk的另一个重要资源是 。 它具有awk的内置函数库的完整参考,以及许多简单和复杂的awk脚本示例。

翻译自:

awk教程

转载地址:http://tpszd.baihongyu.com/

你可能感兴趣的文章
深度图像特征在推荐和广告中的应用(一)
查看>>
U盘FAT32转换NTFS格式
查看>>
CodeForces - 786B Legacy (线段树+DIjkstra+思维)
查看>>
这是用过的"最差"树形插件
查看>>
IBM的人工智能“沃森”首次确诊罕见白血病,只用了10分钟!
查看>>
bzoj 2763: [JLOI2011]飞行路线 分层图
查看>>
Mybatis
查看>>
11th Iran Nationwide Internet Contest 解题报告
查看>>
.net 委托 +lamda表达式
查看>>
第一个shell脚本——修改配置文件
查看>>
hdu_4742_Pinball Game 3D(cdq分治+树状数组)
查看>>
78. Subsets
查看>>
关于assert和de-assert的解释
查看>>
nodejs语法问题
查看>>
bzoj2190: [SDOI2008]仪仗队(欧拉)
查看>>
hdoj 1013
查看>>
HAproxy的安装配置及动静分离
查看>>
Vue2.0 的漫长学习ing-2-1
查看>>
oracle触发器和存储过程的格式
查看>>
xml的介绍
查看>>