Shell下的AWK语法小解.docx

上传人:b****7 文档编号:10769425 上传时间:2023-02-22 格式:DOCX 页数:26 大小:26.52KB
下载 相关 举报
Shell下的AWK语法小解.docx_第1页
第1页 / 共26页
Shell下的AWK语法小解.docx_第2页
第2页 / 共26页
Shell下的AWK语法小解.docx_第3页
第3页 / 共26页
Shell下的AWK语法小解.docx_第4页
第4页 / 共26页
Shell下的AWK语法小解.docx_第5页
第5页 / 共26页
点击查看更多>>
下载资源
资源描述

Shell下的AWK语法小解.docx

《Shell下的AWK语法小解.docx》由会员分享,可在线阅读,更多相关《Shell下的AWK语法小解.docx(26页珍藏版)》请在冰豆网上搜索。

Shell下的AWK语法小解.docx

Shell下的AWK语法小解

Shell编程下的AWK语法小结

目录

目录1

1AWK简介2

2了解字段2

3使用模式4

4花括号和字段分隔符9

5添加文本13

6数学操作14

7BEGIN和END16

8输入、输出和源文件17

9处理错误21

结论21

 

AWK实用工具带有其自己的自包含语言,它是Unix/Linux中也是任何环境中现有的功能最强大的数据处理引擎之一。

这种编程及数据操作语言(其名称得自于它的创始人AlfredAho、PeterWeinberger和BrianKernighan姓氏的首个字母)的最大功能取决于一个人所拥有的知识。

它允许您创建简短的程序,这些程序读取输入文件、为数据排序、处理数据、对输入执行计算以及生成报表,还有无数其他的功能。

1AWK简介

最简单地说,AWK是一种用于处理文本的编程语言工具。

AWK实用工具的语言在很多方面类似于shell编程语言,尽管AWK具有完全属于其本身的语法。

在最初创造AWK时,其目的是用于文本处理,并且这种语言的基础是,只要在输入数据中有模式匹配,就执行一系列指令。

该实用工具扫描文件中的每一行,查找与命令行中所给定内容相匹配的模式。

如果发现匹配内容,则进行下一个编程步骤。

如果找不到匹配内容,则继续处理下一行。

尽管操作可能会很复杂,但命令的语法始终是:

awk'{pattern+action}'

其中pattern表示AWK在数据中查找的内容,而action是在找到匹配内容时所执行的一系列命令。

花括号({})不需要在程序中始终出现,但它们用于根据特定的模式对一系列指令进行分组。

2了解字段

实用工具将每个输入行分为记录和字段。

记录是单行的输入,而每条记录包含若干字段。

默认的字段分隔符是空格或制表符,而记录的分隔符是换行。

虽然在默认情况下将制表符和空格都看作字段分隔符(多个空格仍然作为一个分隔符),但是可以将分隔符从空格改为任何其它字符。

为了进行演示,请查看以下保存为emp_names的员工列表文件:

46012DULANEYEVANMOBILEAL

46013DURHAMJEFFMOBILEAL

46015STEENBILLMOBILEAL

46017FELDMANEVANMOBILEAL

46018SWIMSTEVEUNKNOWNAL

46019BOGUEROBERTPHOENIXAZ

46021JUNEMICAHPHOENIXAZ

46022KANESHERYLUNKNOWNAR

46024WOODWILLIAMMUNCIEIN

46026FERGUSSARAHMUNCIEIN

46027BUCKSARAHMUNCIEIN

46029TUTTLEBOBMUNCIEIN

当AWK读取输入内容时,整条记录被分配给变量。

每个字段以字段分隔符分开,被分配给变量$1、$2等等。

一行在本质上可以包含无数个字段,通过字段号来访问每个字段。

因此,命令

awk'{print$1,$2,$3,$4,$5}'emp_names

将会产生的打印输出是

46012DULANEYEVANMOBILEAL

46013DURHAMJEFFMOBILEAL

46015STEENBILLMOBILEAL

46017FELDMANEVANMOBILEAL

46018SWIMSTEVEUNKNOWNAL

46019BOGUEROBERTPHOENIXAZ

46021JUNEMICAHPHOENIXAZ

46022KANESHERYLUNKNOWNAR

46024WOODWILLIAMMUNCIEIN

46026FERGUSSARAHMUNCIEIN

46027BUCKSARAHMUNCIEIN

46029TUTTLEBOBMUNCIEIN

值得注意的一项重要内容是,AWK解释由空格分隔的五个字段,但当它打印显示内容时,在每个字段间只有一个空格。

利用为每个字段指定了唯一号码的功能,您可以选择只打印特定的字段。

例如,只打印每条记录的姓名时,只需选择第二个和第三个字段进行打印:

$awk'{print$2,$3}'emp_names

DULANEYEVAN

DURHAMJEFF

STEENBILL

FELDMANEVAN

SWIMSTEVE

BOGUEROBERT

JUNEMICAH

KANESHERYL

WOODWILLIAM

FERGUSSARAH

BUCKSARAH

TUTTLEBOB

$

您还可以指定按任何顺序打印字段,而无论它们在记录中是如何存在的。

因此,只需要显示姓名字段,并且使其顺序颠倒,先显示名字再显示姓氏:

$awk'{print$3,$2}'emp_names

EVANDULANEY

JEFFDURHAM

BILLSTEEN

EVANFELDMAN

STEVESWIM

ROBERTBOGUE

MICAHJUNE

SHERYLKANE

WILLIAMWOOD

SARAHFERGUS

SARAHBUCK

BOBTUTTLE

$

3使用模式

通过包含一个必须匹配的模式,您可以选择只对特定的记录而不是所有的记录进行操作。

模式匹配的最简单形式是搜索,其中要匹配的项目被包含在斜线(/pattern/)中。

例如,只对那些居住在阿拉巴马州的员工执行前面的操作:

$awk'/AL/{print$3,$2}'emp_names

EVANDULANEY

JEFFDURHAM

BILLSTEEN

EVANFELDMAN

STEVESWIM

$

如果您不指定要打印的字段,则会打印整个匹配的条目:

$awk'/AL/'emp_names

46012DULANEYEVANMOBILEAL

46013DURHAMJEFFMOBILEAL

46015STEENBILLMOBILEAL

46017FELDMANEVANMOBILEAL

46018SWIMSTEVEUNKNOWNAL

$

对同一数据集的多个命令可以用分号(;)分隔开。

例如,在一行中打印姓名,而在另一行中打印城市和州名:

原始记录46012DULANEYEVANMOBILEAL

$awk'/AL/{print$3,$2;print$4,$5}'emp_names

EVANDULANEY

MOBILEAL

JEFFDURHAM

MOBILEAL

BILLSTEEN

MOBILEAL

EVANFELDMAN

MOBILEAL

STEVESWIM

UNKNOWNAL

$

如果没有使用分号(print$3,$2,$4,$5),则会在同一行中显示所有内容。

另一方面,如果分别给出两个打印语句,则会产生完全不同的结果:

$awk'/AL/{print$3,$2}{print$4,$5}'emp_names

EVANDULANEY

MOBILEAL

JEFFDURHAM

MOBILEAL

BILLSTEEN

MOBILEAL

EVANFELDMAN

MOBILEAL

STEVESWIM

UNKNOWNAL

PHOENIXAZ

PHOENIXAZ

UNKNOWNAR

MUNCIEIN

MUNCIEIN

MUNCIEIN

MUNCIEIN

$

只有在列表中找到AL时才会给出字段三和字段二。

但是,字段四和字段五是无条件的,始终打印它们。

只有第一组花括号中的命令对前面紧邻的命令(/AL/)起作用(注解:

第二组花括号中的命令也会执行,但是模式不会应用到它)。

结果非常不便于阅读,可以使其稍微更清晰一些。

首先,在城市与州之间插入一个空格和逗号。

然后,在每两行显示之后放置一个空行:

$awk'/AL/{print$3,$2;print$4","$5"\n"}'emp_names

EVANDULANEY

MOBILE,AL

JEFFDURHAM

MOBILE,AL

BILLSTEEN

MOBILE,AL

EVANFELDMAN

MOBILE,AL

STEVESWIM

UNKNOWN,AL

$

在第四和第五个字段之间,添加一个逗号和一个空格(在引号之间),在第五个字段后面,打印一个换行符(\n)。

在AWK打印语句中还可以使用那些可在echo命令中使用的所有特殊字符,包括:

\n(换行)

\t(制表)

\b(退格)

\f(进纸)

\r(回车)

因此,要读取全部五个最初由制表符分隔开的字段,并且也利用制表符打印它们,您可以编程如下

$awk'{print$1"\t"$2"\t"$3"\t"$4"\t"$5}'emp_names

46012DULANEYEVANMOBILEAL

46013DURHAMJEFFMOBILEAL

46015STEENBILLMOBILEAL

46017FELDMANEVANMOBILEAL

46018SWIMSTEVEUNKNOWNAL

46019BOGUEROBERTPHOENIXAZ

46021JUNEMICAHPHOENIXAZ

46022KANESHERYLUNKNOWNAR

46024WOODWILLIAMMUNCIEIN

46026FERGUSSARAHMUNCIEIN

46027BUCKSARAHMUNCIEIN

46029TUTTLEBOBMUNCIEIN

$

通过连续设置多项标准并用管道(|)符号将其分隔开,您可以一次搜索多个模式匹配:

$awk'/AL|IN/'emp_names

46012DULANEYEVANMOBILEAL

46013DURHAMJEFFMOBILEAL

46015STEENBILLMOBILEAL

46017FELDMANEVANMOBILEAL

46018SWIMSTEVEUNKNOWNAL

46024WOODWILLIAMMUNCIEIN

46026FERGUSSARAHMUNCIEIN

46027BUCKSARAHMUNCIEIN

46029TUTTLEBOBMUNCIEIN

$

这样可找到每个阿拉巴马州和印第安那州居民的匹配记录。

但是在试图找出居住在亚利桑那州的人时,出现了一个问题:

$awk'/AR/'emp_names

46019BOGUEROBERTPHOENIXAZ

46021JUNEMICAHPHOENIXAZ

46022KANESHERYLUNKNOWNAZ

46026FERGUSSARAHMUNCIEIN

46027BUCKSARAHMUNCIEIN

$

员工46026和46027没有住在亚利桑那州;但是他们的名字中包含所搜索的字符序列。

切记,当在AWK中进行模式匹配时,例如grep、sed或者大部分其他Linux/Unix命令,将在记录(行)中的任何位置查找匹配,除非指定进行其他操作。

为解决这一问题,必须将搜索与特定字段联系起来。

通过利用代字号(~)以及对特定字段的说明,可以达到这一目的,如下例所示:

$awk'$5~/AR/'emp_names

46019BOGUEROBERTPHOENIXAZ

46021JUNEMICAHPHOENIXAZ

46022KANESHERYLUNKNOWNAZ

$

代字号(表示匹配)的对应符号是一个前面带有感叹号的代字号(~?

)。

这些字符通知程序,如果搜索序列没有出现在指定字段中,则找出与搜索序列相匹配的所有行:

$awk'$5!

~/AR/'emp_names

46012DULANEYEVANMOBILEAL

46013DURHAMJEFFMOBILEAL

46015STEENBILLMOBILEAL

46017FELDMANEVANMOBILEAL

46018SWIMSTEVEUNKNOWNAL

46024WOODWILLIAMMUNCIEIN

46026FERGUSSARAHMUNCIEIN

46027BUCKSARAHMUNCIEIN

46029TUTTLEBOBMUNCIEIN

$

在这种情况下,将显示第五个字段中没有AR的所有行—包括两个Sarah条目,这两个条目确实包含AR,但却是在第三个字段而不是第五个字段中。

4花括号和字段分隔符

括号字符在AWK命令中起着很重要的作用。

出现在括号之间的操作指出将要发生什么以及何时发生。

当只使用一对括号时:

{print$3,$2}

括号间的所有操作同时发生。

当使用多于一对的括号时:

{print$3}{print$2}

执行第一组命令,在该命令完成后执行第二组命令。

注意以下两列清单的区别:

$awk'{print$3,$2}'names

EVANDULANEY

JEFFDURHAM

BILLSTEEN

EVANFELDMAN

STEVESWIM

ROBERTBOGUE

MICAHJUNE

SHERYLKANE

WILLIAMWOOD

SARAHFERGUS

SARAHBUCK

BOBTUTTLE

$

$awk'{print$3}{print$2}'names

EVAN

DULANEY

JEFF

DURHAM

BILL

STEEN

EVAN

FELDMAN

STEVE

SWIM

ROBERT

BOGUE

MICAH

JUNE

SHERYL

KANE

WILLIAM

WOOD

SARAH

FERGUS

SARAH

BUCK

BOB

TUTTLE

$

要利用多组括号进行重复查找,执行第一组中的命令直到完成为止;然后处理第二组命令。

如果有第三组命令,则在第二组命令完成后执行它,以此类推。

在所生成的打印输出中,有两个分隔的打印命令,因此先执行第一个命令,随后执行第二个命令,这样导致每个条目显示在两行而不是一行中。

区分两个字段的字段分隔符不一定始终是空格;它可以是任何可识别的字符。

为进行演示,假定emp_names文件利用冒号而不是制表符来分隔字段:

$catemp_names

46012:

DULANEY:

EVAN:

MOBILE:

AL

46013:

DURHAM:

JEFF:

MOBILE:

AL

46015:

STEEN:

BILL:

MOBILE:

AL

46017:

FELDMAN:

EVAN:

MOBILE:

AL

46018:

SWIM:

STEVE:

UNKNOWN:

AL

46019:

BOGUE:

ROBERT:

PHOENIX:

AZ

46021:

JUNE:

MICAH:

PHOENIX:

AZ

46022:

KANE:

SHERYL:

UNKNOWN:

AR

46024:

WOOD:

WILLIAM:

MUNCIE:

IN

46026:

FERGUS:

SARAH:

MUNCIE:

IN

46027:

BUCK:

SARAH:

MUNCIE:

IN

46029:

TUTTLE:

BOB:

MUNCIE:

IN

$

如果试图通过指定所需要的第二个字段来打印姓氏

$awk'{print$2}'emp_names

您最后会得到十二个空行。

因为文件中没有空格,除了第一个字段之外没有可认别的字段。

为解决这一问题,必须通知AWK是空格之外的另一个字符作为分隔符,有两种方法可通知AWK使用新的字段分隔符:

使用命令行参数-F,或在程序中指定变量FS。

两种方法的效果相同,只有一种例外情况,如下例所示:

$awk'{FS=":

"}{print$2}'emp_names

DURHAM

STEEN

FELDMAN

SWIM

BOGUE

JUNE

KANE

WOOD

FERGUS

BUCK

TUTTLE

$

$awk-F:

'{print$2}'emp_names

DULANEY

DURHAM

STEEN

FELDMAN

SWIM

BOGUE

JUNE

KANE

WOOD

FERGUS

BUCK

TUTTLE

$

在第一个命令中,头一条记录返回不正确的空行,而其他结果正确。

直到读取第二条记录时,才识别字段分隔符并正确地执行。

通过使用BEGIN语句可以纠正这一缺点(在后文详述)。

-F的功能非常类似于BEGIN,能够正确地读取第一条记录并按要求执行。

在本文开始处我曾提到,默认的显示/输出字段分隔符是空格。

通过使用输出字段分隔符(OFS)变量,可以在程序中更改此特性。

例如,要读取文件(由冒号分隔)并以短划线显示,则命令是

$awk-F":

"'{OFS="-"}{print$1,$2,$3,$4,$5}'emp_names

46012-DULANEY-EVAN-MOBILE-AL

46013-DURHAM-JEFF-MOBILE-AL

46015-STEEN-BILL-MOBILE-AL

46017-FELDMAN-EVAN-MOBILE-AL

46018-SWIM-STEVE-UNKNOWN-AL

46019-BOGUE-ROBERT-PHOENIX-AZ

46021-JUNE-MICAH-PHOENIX-AZ

46022-KANE-SHERYL-UNKNOWN-AR

46024-WOOD-WILLIAM-MUNCIE-IN

46026-FERGUS-SARAH-MUNCIE-IN

46027-BUCK-SARAH-MUNCIE-IN

46029-TUTTLE-BOB-MUNCIE-IN

$

FS和OFS是(输入)字段分隔符和输出字段分隔符,它们只是一对可以在AWK实用工具中使用的变量。

例如,要在打印时为每行编号,可以采用以下方式使用NR变量:

$awk-F":

"'{printNR,$1,$2,$3}'emp_names

146012DULANEYEVAN

246013DURHAMJEFF

346015STEENBILL

446017FELDMANEVAN

546018SWIMSTEVE

646019BOGUEROBERT

746021JUNEMICAH

846022KANESHERYL

946024WOODWILLIAM

1046026FERGUSSARAH

1146027BUCKSARAH

1246029TUTTLEBOB

$

找出员工号码处于46012和46015之间的所有行:

$awk-F":

"'/4601[2-5]/'emp_names

46012DULANEYEVANMOBILEAL

46013DURHAMJEFFMOBILEAL

46015STEENBILLMOBILEAL

$

5添加文本

可以按照添加控制序列或其他字符的相同方式将文本添加到显示中。

例如,要将分隔符从空格改为冒号,则命令是

awk'{print":

"":

"":

"":

"}'emp_names>new_emp_names

在这种情况下,字符(:

)包含在引号("/")中,它被添加到每个字段之间。

在引号之间的值可以是任何内容。

例如,创建一个关于居住在阿拉巴马州的员工的外观类似数据库的显示:

$awk'{print$1":

"$2":

"$3":

"$4":

"$5}'emp_names>new_emp_names

NAME:

DULANEY,EVAN

CITY-STATE:

MOBILE,AL

NAME:

DURHAM,JEFF

CITY-STATE:

MOBILE,AL

NAME:

STEEN,BILL

CITY-STATE:

MOBILE,AL

NAME:

FELDMAN,EVAN

CITY-STATE:

MOBILE,AL

NAME:

SWIM,STEVE

CITY-STATE:

UNKNOWN,AL

$

6数学操作

AWK除了提供文本功能,还提供全部范围的算术操作符,包括以下符号:

+将数字相加

-减

*乘

/除

^执行指数运算

%提供模

++将变量值加一

+=将其他操作的结果分配给变量

—将变量减一

-=将减法操作的结果分配给变量

*=分配乘法操作的结果

/=分配除法操作的结果

%=分配求模操作的结果

例如,假定您的机器上存在以下的文件,详细地列出硬件商店中的物品:

$catinventory

hammers57.99

drills229.99

punches73.59

drifts24.09

bits551.19

saws12314.99

nails800.19

screws80.29

brads100.24

$

第一项业务定单是通过将第二个字段(数量)的值乘以第三个字段(价格)的值,计算每种物品的库存价值:

$awk'{print$1,"QTY:

"$2,"PRICE:

"$3,"TOTAL:

"$2*$3}'inventory

hammersQTY:

5PRICE:

7.99TOTAL:

39.95

drillsQTY:

2PRICE:

29.99TOTAL:

59.98

punchesQTY:

7PRICE:

3.59TOTAL:

25.13

driftsQTY:

2PRICE:

4.09TOTAL:

8.18

bitsQTY:

55PRICE:

1.19TOTAL:

65.45

sawsQTY:

123PRICE:

14.99TOTAL:

1843.77

nailsQTY:

800PRICE:

.19TOTAL:

152

screwsQTY:

80PRICE:

.29TOTAL:

23.2

bradsQTY:

100PRICE:

.24TOTAL:

24

$

如果这些行本身并不重要,您只是希望确定商店中有多少件物品,则可以分配一个普通变量,按照每条记录中的物品数量增加:

$awk'{x=x+$2}{printx}'inventory

5

7

14

16

71

194

994

1074

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 高等教育 > 哲学

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1