AWK编程实例Word文档格式.docx
《AWK编程实例Word文档格式.docx》由会员分享,可在线阅读,更多相关《AWK编程实例Word文档格式.docx(30页珍藏版)》请在冰点文库上搜索。
![AWK编程实例Word文档格式.docx](https://file1.bingdoc.com/fileroot1/2023-4/30/3c86894f-e281-442d-a786-d1e166cba307/3c86894f-e281-442d-a786-d1e166cba3071.gif)
46024WOODWILLIAMMUNCIEIN
46026FERGUSSARAHMUNCIEIN
46027BUCKSARAHMUNCIEIN
46029TUTTLEBOBMUNCIEIN
当AWK读取输入内容时,整条记录被分配给变量$0。
每个字段以字段分隔符分开,被分配给变量$1、$2、$3等等。
一行在本质上可以包含无数个字段,通过字段号来访问每个字段。
因此,命令
{print$1,$2,$3,$4,$5}'
names
将会产生的打印输出是
值得注意的一项重要内容是,AWK解释由空格分隔的五个字段,但当它打印显示内容时,在每个字段间只有一个空格。
利用为每个字段指定了唯一号码的功能,您可以选择只打印特定的字段。
例如,只打印每条记录的姓名时,只需选择第二个和第三个字段进行打印:
$awk'
{print$2,$3}'
emp_names
DULANEYEVAN
DURHAMJEFF
STEENBILL
FELDMANEVAN
SWIMSTEVE
BOGUEROBERT
JUNEMICAH
KANESHERYL
WOODWILLIAM
FERGUSSARAH
BUCKSARAH
TUTTLEBOB
$
您还可以指定按任何顺序打印字段,而无论它们在记录中是如何存在的。
因此,只需要显示姓名字段,并且使其顺序颠倒,先显示名字再显示姓氏:
{print$3,$2}'
EVANDULANEY
JEFFDURHAM
BILLSTEEN
EVANFELDMAN
STEVESWIM
ROBERTBOGUE
MICAHJUNE
SHERYLKANE
WILLIAMWOOD
SARAHFERGUS
SARAHBUCK
BOBTUTTLE
使用模式
通过包含一个必须匹配的模式,您可以选择只对特定的记录而不是所有的记录进行操作。
模式匹配的最简单形式是搜索,其中要匹配的项目被包含在斜线(/pattern/)中。
例如,只对那些居住在阿拉巴马州的员工执行前面的操作:
/AL/{print$3,$2}'
如果您不指定要打印的字段,则会打印整个匹配的条目:
/AL/'
对同一数据集的多个命令可以用分号(;
)分隔开。
例如,在一行中打印姓名,而在另一行中打印城市和州名:
/AL/{print$3,$2;
print$4,$5}'
MOBILEAL
UNKNOWNAL
如果没有使用分号(print$3,$2,$4,$5),则会在同一行中显示所有内容。
另一方面,如果分别给出两个打印语句,则会产生完全不同的结果:
/AL/{print$3,$2}{print$4,$5}'
PHOENIXAZ
UNKNOWNAR
MUNCIEIN
只有在列表中找到AL时才会给出字段三和字段二。
但是,字段四和字段五是无条件的,始终打印它们。
只有第一组花括号中的命令对前面紧邻的命令(/AL/)起作用。
结果非常不便于阅读,可以使其稍微更清晰一些。
首先,在城市与州之间插入一个空格和逗号。
然后,在每两行显示之后放置一个空行:
print$4"
"
$5"
\n"
}'
MOBILE,AL
UNKNOWN,AL
在第四和第五个字段之间,添加一个逗号和一个空格(在引号之间),在第五个字段后面,打印一个换行符(\n)。
在AWK打印语句中还可以使用那些可在echo命令中使用的所有特殊字符,包括:
\n(换行)
\t(制表)
\b(退格)
\f(进纸)
\r(回车)
因此,要读取全部五个最初由制表符分隔开的字段,并且也利用制表符打印它们,您可以编程如下
{print$1"
\t"
$2"
$3"
$4"
$5}'
46021JUNEMICAHPHOENIXAZ
46022KANESHERYLUNKNOWNAR
46024WOODWILLIAMMUNCIEIN
46026FERGUSSARAHMUNCIEIN
46027BUCKSARAHMUNCIEIN
通过连续设置多项标准并用管道(|)符号将其分隔开,您可以一次搜索多个模式匹配:
/AL|IN/'
这样可找到每个阿拉巴马州和印第安那州居民的匹配记录。
但是在试图找出居住在亚利桑那州的人时,出现了一个问题:
/AR/'
46022KANESHERYLUNKNOWNAZ
员工46026和46027没有住在亚利桑那州;
但是他们的名字中包含所搜索的字符序列。
切记,当在AWK中进行模式匹配时,例如grep、sed或者大部分其他Linux/Unix命令,将在记录(行)中的任何位置查找匹配,除非指定进行其他操作。
为解决这一问题,必须将搜索与特定字段联系起来。
通过利用代字号(?
)以及对特定字段的说明,可以达到这一目的,如下例所示:
$5?
/AR/'
代字号(表示匹配)的对应符号是一个前面带有感叹号的代字号(!
?
)。
这些字符通知程序,如果搜索序列没有出现在指定字段中,则找出与搜索序列相匹配的所有行:
$5!
names
在这种情况下,将显示第五个字段中没有AR的所有行—包括两个Sarah条目,这两个条目确实包含AR,但却是在第三个字段而不是第五个字段中。
花括号和字段分隔符
括号字符在AWK命令中起着很重要的作用。
出现在括号之间的操作指出将要发生什么以及何时发生。
当只使用一对括号时:
括号间的所有操作同时发生。
{print$3,$2}
当使用多于一对的括号时:
执行第一组命令,在该命令完成后执行第二组命令。
{print$3}{print$2}
注意以下两列清单的区别:
{print$3}{print$2}'
EVAN
DULANEY
JEFF
DURHAM
BILL
STEEN
FELDMAN
STEVE
SWIM
ROBERT
BOGUE
MICAH
JUNE
SHERYL
KANE
WILLIAM
WOOD
SARAH
FERGUS
BUCK
BOB
TUTTLE
要利用多组括号进行重复查找,执行第一组中的命令直到完成为止;
然后处理第二组命令。
如果有第三组命令,则在第二组命令完成后执行它,以此类推。
在所生成的打印输出中,有两个分隔的打印命令,因此先执行第一个命令,随后执行第二个命令,这样导致每个条目显示在两行而不是一行中。
区分两个字段的字段分隔符不一定始终是空格;
它可以是任何可识别的字符。
为进行演示,假定emp_names文件利用冒号而不是制表符来分隔字段:
$catemp_names
46012:
DULANEY:
EVAN:
MOBILE:
AL
46013:
DURHAM:
JEFF:
46015:
STEEN:
BILL:
46017:
FELDMAN:
46018:
SWIM:
STEVE:
UNKNOWN:
46019:
BOGUE:
ROBERT:
PHOENIX:
AZ
46021:
JUNE:
MICAH:
46022:
KANE:
SHERYL:
AR
46024:
WOOD:
WILLIAM:
MUNCIE:
IN
46026:
FERGUS:
SARAH:
46027:
BUCK:
46029:
TUTTLE:
BOB:
如果试图通过指定所需要的第二个字段来打印姓氏
{print$2}'
emp_names
您最后会得到十二个空行。
因为文件中没有空格,除了第一个字段之外没有可认别的字段。
为解决这一问题,必须通知AWK是空格之外的另一个字符作为分隔符,有两种方法可通知AWK使用新的字段分隔符:
使用命令行参数-F,或在程序中指定变量FS。
两种方法的效果相同,只有一种例外情况,如下例所示:
{FS="
:
"
}{print$2}'
$awk-F:
'
在第一个命令中,头一条记录返回不正确的空行,而其他结果正确。
直到读取第二条记录时,才识别字段分隔符并正确地执行。
通过使用BEGIN语句可以纠正这一缺点(在后文详述)。
-F的功能非常类似于BEGIN,能够正确地读取第一条记录并按要求执行。
在本文开始处我曾提到,默认的显示/输出字段分隔符是空格。
通过使用输出字段分隔符(OFS)变量,可以在程序中更改此特性。
例如,要读取文件(由冒号分隔)并以短划线显示,则命令是
$awk-F"
{OFS="
-"
}{print$1,$2,$3,$4,$5}'
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变量:
{printNR,$1,$2,$3}'
146012DULANEYEVAN
246013DURHAMJEFF
346015STEENBILL
446017FELDMANEVAN
546018SWIMSTEVE
646019BOGUEROBERT
746021JUNEMICAH
846022KANESHERYL
946024WOODWILLIAM
1046026FERGUSSARAH
1146027BUCKSARAH
1246029TUTTLEBOB
找出员工号码处于46012和46015之间的所有行:
/4601[2-5]/'
BEGIN{sum=1};
{print$1"
};
{sum=sum+$1};
END{printsum}'
file
awk-vsum=1'
file
Built-inVariables
Gawk’sbuilt-invariablesare:
ARGCThenumberofcommandlinearguments(doesnotincludeoptionstogawk,ortheprogramsource).
ARGINDTheindexinARGVofthecurrentfilebeingprocessed.
ARGVArrayofcommandlinearguments.Thearrayisindexedfrom0toARGC-1.DynamicallychangingthecontentsofARGVcancontrolthe
filesusedfordata.
BINMODEOnnon-POSIXsystems,specifiesuseofâ
€œbinaryâ
€?
modeforallfileI/O.Numericvaluesof1,2,or3,specifythatinputfiles,output
files,orallfiles,respectively,shouldusebinaryI/O.Stringvaluesof"
r"
or"
w"
specifythatinputfiles,oroutputfiles,
respectively,shouldusebinaryI/O.Stringvaluesof"
rw"
or"
wr"
specifythatallfilesshouldusebinaryI/O.Anyotherstring
valueistreatedas"
butgeneratesawarningmessage.
CONVFMTTheconversionformatfornumbers,"
%.6g"
bydefault.
ENVIRONAnarraycontainingthevaluesofthecurrentenvironment.Thearrayisindexedbytheenvironmentvariables,eachelementbeingthe
valueofthatvariable(e.g.,ENVIRON["
HOME"
]mightbe/home/arnold).Changingthisarraydoesnotaffecttheenvironmentseenby
programswhichgawkspawnsviaredirectionorthesystem()function.
ERRNOIfasystemerroroccurseitherdoingaredirectionforgetline,duringa