AWK

转自 :http://hi.baidu.com/cjy2020/item/865ca5099479a6d01ff046a6
shell

AWK 实用工具带有其本身的自包含语言,它不只是 Linux 中也是任何环境中现有的功能最强大的数据处理引擎之一。这种编程及数据操做语言(其名称得自于它的创始人 Alfred Aho、Peter Weinberger 和 Brian Kernighan 姓氏的首个字母)的最大功能取决于一我的所拥有的知识。它容许您建立简短的程序,这些程序读取输入文件、为数据排序、处理数据、对输入执行计算以及生成报表,还有无数其余的功能。  数据库


AWK 是什么? 

最简单地说,AWK 是一种用于处理文本的编程语言工具。AWK 实用工具的语言在不少方面相似于 shell 编程语言,尽管 AWK 具备彻底属于其自己的语法。在最初创造 AWK 时,其目的是用于文本处理,而且这种语言的基础是,只要在输入数据中有模式匹配,就执行一系列指令。该实用工具扫描文件中的每一行,查找与命令行中所给定内容相匹配的模式。若是发现匹配内容,则进行下一个编程步骤。若是找不到匹配内容,则继续处理下一行。 

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

awk '{pattern + action}' {filenames} 

其中 pattern 表示 AWK 在数据中查找的内容,而 action 是在找到匹配内容时所执行的一系列命令。花括号 ({}) 不须要在程序中始终出现,但它们用于根据特定的模式对一系列指令进行分组。 

了解字段 

实用工具将每一个输入行分为记录和字段。记录是单行的输入,而每条记录包含若干字段。默认的字段分隔符是空格或制表符,而记录的分隔符是换行。虽然在默认状况下将制表符和空格都看做字段分隔符(多个空格仍然做为一个分隔符),可是能够将分隔符从空格改成任何其它字符。 

为了进行演示,请查看如下保存为 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 

当 AWK 读取输入内容时,整条记录被分配给变量 $0。每一个字段以字段分隔符分开,被分配给变量 $一、$二、$3 等等。一行在本质上能够包含无数个字段,经过字段号来访问每一个字段。所以,命令 

awk '{print $1,$2,$3,$4,$5}' 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 解释由空格分隔的五个字段,但当它打印显示内容时,在每一个字段间只有一个空格。利用为每一个字段指定了惟一号码的功能,您能够选择只打印特定的字段。例如,只打印每条记录的姓名时,只需选择第二个和第三个字段进行打印: 

$ awk '{print $2,$3}' emp_names 
DULANEY EVAN 
DURHAM JEFF 
STEEN BILL 
FELDMAN EVAN 
SWIM STEVE 
BOGUE ROBERT 
JUNE MICAH 
KANE SHERYL 
WOOD WILLIAM 
FERGUS SARAH 
BUCK SARAH 
TUTTLE BOB 


您还能够指定按任何顺序打印字段,而不管它们在记录中是如何存在的。所以,只须要显示姓名字段,而且使其顺序颠倒,先显示名字再显示姓氏: 

$ awk '{print $3,$2}' emp_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 


使用模式 

经过包含一个必须匹配的模式,您能够选择只对特定的记录而不是全部的记录进行操做。模式匹配的最简单形式是搜索,其中要匹配的项目被包含在斜线 (/pattern/) 中。例如,只对那些居住在阿拉巴马州的员工执行前面的操做: 

$ awk '/AL/ {print $3,$2}' emp_names 
EVAN DULANEY 
JEFF DURHAM 
BILL STEEN 
EVAN FELDMAN 
STEVE SWIM 


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

$ awk '/AL/' 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 


对同一数据集的多个命令能够用分号 (;) 分隔开。例如,在一行中打印姓名,而在另外一行中打印城市和州名: 

$ awk '/AL/ {print $3,$2 ; print $4,$5}' emp_names 
EVAN DULANEY 
MOBILE AL 
JEFF DURHAM 
MOBILE AL 
BILL STEEN 
MOBILE AL 
EVAN FELDMAN 
MOBILE AL 
STEVE SWIM 
UNKNOWN AL 


若是没有使用分号 (print $3,$2,$4,$5),则会在同一行中显示全部内容。另外一方面,若是分别给出两个打印语句,则会产生彻底不一样的结果: 

$ awk '/AL/ {print $3,$2} {print $4,$5}' emp_names 
EVAN DULANEY 
MOBILE AL 
JEFF DURHAM 
MOBILE AL 
BILL STEEN 
MOBILE AL 
EVAN FELDMAN 
MOBILE AL 
STEVE SWIM 
UNKNOWN AL 
PHOENIX AZ 
PHOENIX AZ 
UNKNOWN AR 
MUNCIE IN 
MUNCIE IN 
MUNCIE IN 
MUNCIE IN 


只有在列表中找到 AL 时才会给出字段三和字段二。可是,字段四和字段五是无条件的,始终打印它们。只有第一组花括号中的命令对前面紧邻的命令 (/AL/) 起做用。 

结果很是不便于阅读,可使其稍微更清晰一些。首先,在城市与州之间插入一个空格和逗号。而后,在每两行显示以后放置一个空行: 

$ awk '/AL/ {print $3,$2 ; print $4", "$5" "}' emp_names 
EVAN DULANEY 
MOBILE, AL 

JEFF DURHAM 
MOBILE, AL 

BILL STEEN 
MOBILE, AL 

EVAN FELDMAN 
MOBILE, AL 

STEVE SWIM 
UNKNOWN, AL 


在第四和第五个字段之间,添加一个逗号和一个空格(在引号之间),在第五个字段后面,打印一个换行符 ( )。在 AWK 打印语句中还可使用那些可在 echo 命令中使用的全部特殊字符,包括: 

* (换行) 
* (制表) 
* (退格) 
* f(进纸) 
* (回车) 

所以,要读取所有五个最初由制表符分隔开的字段,而且也利用制表符打印它们,您能够编程以下 

$ awk '{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 


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

$ awk '/AL|IN/' 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 
46024 WOOD WILLIAM MUNCIE IN 
46026 FERGUS SARAH MUNCIE IN 
46027 BUCK SARAH MUNCIE IN 
46029 TUTTLE BOB MUNCIE IN 


这样可找到每一个阿拉巴马州和印第安那州居民的匹配记录。可是在试图找出居住在亚利桑那州的人时,出现了一个问题: 

$ awk '/AR/' emp_names 
46019 BOGUE ROBERT PHOENIX AZ 
46021 JUNE MICAH PHOENIX AZ 
46022 KANE SHERYL UNKNOWN AZ 
46026 FERGUS SARAH MUNCIE IN 
46027 BUCK SARAH MUNCIE IN 


员工 46026 和 46027 没有住在亚利桑那州;可是他们的名字中包含所搜索的字符序列。切记,当在 AWK 中进行模式匹配时,例如 grep、sed 或者大部分其余 Linux/Unix 命令,将在记录(行)中的任何位置查找匹配,除非指定进行其余操做。为解决这一问题,必须将搜索与特定字段联系起来。经过利用代字号 (˜) 以及对特定字段的说明,能够达到这一目的,以下例所示: 

$ awk '$5 ˜ /AR/' emp_names 
46019 BOGUE ROBERT PHOENIX AZ 
46021 JUNE MICAH PHOENIX AZ 
46022 KANE SHERYL UNKNOWN AZ 


代字号(表示匹配)的对应符号是一个前面带有感叹号的代字号 (!˜)。这些字符通知程序,若是搜索序列没有出如今指定字段中,则找出与搜索序列相匹配的全部行: 

$ awk '$5 !˜ /AR/' 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 
46024 WOOD WILLIAM MUNCIE IN 
46026 FERGUS SARAH MUNCIE IN 
46027 BUCK SARAH MUNCIE IN 
46029 TUTTLE BOB MUNCIE IN 


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

花括号和字段分隔符 

括号字符在 AWK 命令中起着很重要的做用。出如今括号之间的操做指出将要发生什么以及什么时候发生。当只使用一对括号时: 

{print $3,$2} 

括号间的全部操做同时发生。当使用多于一对的括号时: 

{print $3}{print $2} 

执行第一组命令,在该命令完成后执行第二组命令。注意如下两列清单的区别: 

$ awk '{print $3,$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 


$ 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 文件利用冒号而不是制表符来分隔字段: 

$ cat 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 


若是试图经过指定所须要的第二个字段来打印姓氏 

$ 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":" '{print NR,$1,$2,$3}' emp_names 
1 46012 DULANEY EVAN 
2 46013 DURHAM JEFF 
3 46015 STEEN BILL 
4 46017 FELDMAN EVAN 
5 46018 SWIM STEVE 
6 46019 BOGUE ROBERT 
7 46021 JUNE MICAH 
8 46022 KANE SHERYL 
9 46024 WOOD WILLIAM 
10 46026 FERGUS SARAH 
11 46027 BUCK SARAH 
12 46029 TUTTLE BOB 


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

$ awk -F":" '/4601[2-5]/' emp_names 
46012 DULANEY EVAN MOBILE AL 
46013 DURHAM JEFF MOBILE AL 
46015 STEEN BILL MOBILE AL 


添加文本 

能够按照添加控制序列或其余字符的相同方式将文本添加到显示中。例如,要将分隔符从空格改成冒号,则命令是 

awk '{print $1":"$2":"$3":"$4":"$5}' emp_names > new_emp_names 

在这种状况下,字符 (:) 包含在引号 ("/") 中,它被添加到每一个字段之间。在引号之间的值能够是任何内容。例如,建立一个关于居住在阿拉巴马州的员工的外观相似数据库的显示: 

$ awk '$5 ~ /AL/ {print "NAME: "$2", "$3" CITY-STATE: 
"$4", "$5" "}' 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 


数学操做 

AWK 除了提供文本功能,还提供所有范围的算术操做符,包括如下符号: 

+ 将数字相加 
- 减 
* 乘 
/ 除 
^ 执行指数运算 
% 提供模 
++ 将变量值加一 
+= 将其余操做的结果分配给变量 
— 将变量减一 
-= 将减法操做的结果分配给变量 
*= 分配乘法操做的结果 
/= 分配除法操做的结果 
%= 分配求模操做的结果 

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

$ cat inventory 
hammers 5 7.99 
drills 2 29.99 
punches 7 3.59 
drifts 2 4.09 
bits 55 1.19 
saws 123 14.99 
nails 800 .19 
screws 80 .29 
brads 100 .24 


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

$ awk '{print $1,"QTY: "$2,"PRICE: "$3,"TOTAL: "$2*$3}' inventory 
hammers QTY: 5 PRICE: 7.99 TOTAL: 39.95 
drills QTY: 2 PRICE: 29.99 TOTAL: 59.98 
punches QTY: 7 PRICE: 3.59 TOTAL: 25.13 
drifts QTY: 2 PRICE: 4.09 TOTAL: 8.18 
bits QTY: 55 PRICE: 1.19 TOTAL: 65.45 
saws QTY: 123 PRICE: 14.99 TOTAL: 1843.77 
nails QTY: 800 PRICE: .19 TOTAL: 152 
screws QTY: 80 PRICE: .29 TOTAL: 23.2 
brads QTY: 100 PRICE: .24 TOTAL: 24 


若是这些行自己并不重要,您只是但愿肯定商店中有多少件物品,则能够分配一个普通变量,按照每条记录中的物品数量增长: 

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


14 
16 
71 
194 
994 
1074 
1174 


根据这一数据,商店中有 1174 件物品。第一次执行时,变量 x 没有值,所以它采用第一行第二个字段的值。第二次执行时,它保留了第一行的值并加上第二行的值,以此类推,直到达到累计的总合。 

能够应用相同的过程来肯定现有库存的总价值: 

$ awk '{x=x+($2*$3)} {print x}' inventory 
39.95 
99.93 
125.06 
133.24 
198.69 
2042.46 
2194.46 
2217.66 
2241.66 


所以,1174 件物品的价值是 $2,241.66。虽然这一过程能够得到总计值,但它的外观不好,须要加工成实际的报表。利用一些附加项,很容易使显示变得更整洁: 

$ awk '{x=x+($2*$3)}{print $1,"QTY: "$2,"PRICE: "$3,"TOTAL: "$2*$3,"BAL: "x}' inventory 
hammers QTY: 5 PRICE: 7.99 TOTAL: 39.95 BAL: 39.95 
drills QTY: 2 PRICE: 29.99 TOTAL: 59.98 BAL: 99.93 
punches QTY: 7 PRICE: 3.59 TOTAL: 25.13 BAL: 125.06 
drifts QTY: 2 PRICE: 4.09 TOTAL: 8.18 BAL: 133.24 
bits QTY: 55 PRICE: 1.19 TOTAL: 65.45 BAL: 198.69 
saws QTY: 123 PRICE: 14.99 TOTAL: 1843.77 BAL: 2042.46 
nails QTY: 800 PRICE: .19 TOTAL: 152 BAL: 2194.46 
screws QTY: 80 PRICE: .29 TOTAL: 23.2 BAL: 2217.66 
brads QTY: 100 PRICE: .24 TOTAL: 24 BAL: 2241.66 


该过程提供了每条记录的清单,同时将总价值分配给库存值,并保持商店资产的运做平衡。 

BEGIN 和 END 

使用 BEGIN 和 END 语句能够分别指定在处理实际开始以前或者完成以后进行操做。BEGIN 语句最经常使用于创建变量或显示标题。另外一方面,END 语句可用于在程序结束后继续进行处理。 

在前面的示例中,利用如下例程生成了物品的总价值: 

awk '{x=x+($2*$3)} {print x}' inventory 

该例程在运行总计累加时显示了文件中的每一行。没有其余方法能够指定它,而不让在每一行进行打印也致使它始终不打印出来。可是,利用 END 语句能够避免这一问题: 

$ awk '{x=x+($2*$3)} END {print "Total Value of Inventory:"x}' inventory 
Total Value of Inventory: 2241.66 


定义了变量 x,它对每一行进行处理;可是,在全部处理完成以前不会生成显示。尽管能够做为独立例程使用,它也能够置入到先前的代码列表,添加更多信息并生成更完整的报表: 

$ awk '{x=x+($2*$3)} {print $1,"QTY: "$2,"PRICE: 
"$3,"TOTAL: "$2*$3} END {print "Total Value of Inventory: " x}' inventory 

hammers QTY: 5 PRICE: 7.99 TOTAL: 39.95 
drills QTY: 2 PRICE: 29.99 TOTAL: 59.98 
punches QTY: 7 PRICE: 3.59 TOTAL: 25.13 
drifts QTY: 2 PRICE: 4.09 TOTAL: 8.18 
bits QTY: 55 PRICE: 1.19 TOTAL: 65.45 
saws QTY: 123 PRICE: 14.99 TOTAL: 1843.77 
nails QTY: 800 PRICE: .19 TOTAL: 152 
screws QTY: 80 PRICE: .29 TOTAL: 23.2 
brads QTY: 100 PRICE: .24 TOTAL: 24 
Total Value of Inventory: 2241.66 


BEGIN 命令与 END 的工做方式相同,但它创建了那些须要在完成其余工做以前所作的项目。该过程最多见的目的是建立报表的标题。此例程的语法相似于 

$ awk 'BEGIN {print "ITEM QUANTITY PRICE TOTAL"}' 

输入、输出和源文件 

AWK 工具能够从文件中读取其输入,正如在此以前全部示例所作的那样,它也能够从其余命令的输出中获取输入。例如: 

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

awk 命令的输入是排序操做的输出。除了 sort,还可使用任何其余的 Linux 命令 — 例如 grep。该过程容许您在离开所选定字段前对文件执行其余操做。 

相似于解释程序,AWK 使用输出改向操做符 > 和 >> 将其输出放入文件中而不是标准输出设备。这些符号的做用相似于它们在解释程序中的对应符号,所以 > 在不存在文件时建立文件,而 >> 追加到现有文件的尾部。请看如下的示例: 

$ awk '{print NR, $1 ) > "/tmp/filez" }' emp_names 
$ cat /tmp/filez 
1 46012 
2 46013 
3 46015 
4 46017 
5 46018 
6 46019 
7 46021 
8 46022 
9 46024 
10 46026 
11 46027 
12 46029 


检查该语句的语法,您会看到输出改向是在打印语句完成后进行的。必须将文件名包含在引号中,不然它只是一个未初始化的 AWK 变量,而将指令联接起来会在 AWK 中产生错误。(若是不正确地使用改向符号,则 AWK 没法了解该符号意味着“改向”仍是一个关系操做符。) 

在 AWK 中输出到管道也相似于解释程序中所实现的相同操做。要将打印命令的输出发送到管道中,能够在打印命令后附加管道符号以及命令的名称,以下所示: 

$ awk '{ print $2 | "sort" }' emp_names 
BOGUE 
BUCK 
DULANEY 
DURHAM 
FELDMAN 
FERGUS 
JUNE 
KANE 
STEEN 
SWIM 
TUTTLE 
WOOD 


这是输出改向的状况,必须将命令包含在引号中,而管道的名称是被执行命令的名称。 

AWK 所使用的命令能够来自两个地方。首先,能够在命令行中指定它们,如示例中所示。其次,它们能够由源文件提供。若是是这种状况,经过 -f 选项将这种状况向 AWK 发出警告。演示以下: 

$ cat awklist 
{print $3,$2} 
{print $4,$5," "} 


$ awk -f awklist emp_names 
EVAN DULANEY 
MOBILE AL 

JEFF DURHAM 
MOBILE AL 

BILL STEEN 
MOBILE AL 

EVAN FELDMAN 
MOBILE AL 

STEVE SWIM 
UNKNOWN AL 

ROBERT BOGUE 
PHOENIX AZ 

MICAH JUNE 
PHOENIX AZ 

SHERYL KANE 
UNKNOWN AR 

WILLIAM WOOD 
MUNCIE IN 

SARAH FERGUS 
MUNCIE IN 

SARAH BUCK 
MUNCIE IN 

BOB TUTTLE 
MUNCIE IN 



注意,在源文件中的任何地方或者在命令行中调用它时,不使用单引号。单引号只用于区别命令行中的命令与文件名称。 

若是简单的输出不能处理您的程序中所须要的复杂信息,则能够尝试由 printf 命令得到的更加复杂的输出,其语法是 

printf( format, value, value ...) 

该语法相似于 C 语言中的 printf 命令,而格式的规格是相同的。经过插入一项定义如何打印数值的规格,能够定义该格式。格式规格包含一个跟有字母的 %。相似于打印命令,printf 没必要包含在圆括号中,可是能够认为使用圆括号是一种良好的习惯。 

下表列出 printf 命令提供的各类规格。 

规格 说明 
%c 打印单个 ASCII 字符 
%d 打印十进制数 
%e 打印数字的科学计数表示 
%f 打印浮点表示 
%g 打印 %e 或 %f;两种方式都更简短 
%o 打印无符号的八进制数 
s 打印 ASCII 字符串 
%x 打印无符号的十六进制数 
%% 打印百分号;不执行转换 

能够在 % 与字符之间提供某些附加的格式化参数。这些参数进一步改进数值的打印方式: 

参数 说明 
- 将字段中的表达式向左对齐 
,width 根据须要将字段补齐到指定宽度(前导零使用零将字段补齐) 
.prec 小数点右面数字的最大字符串宽度或最大数量 

printf 命令可以控制并将数值从一种格式转换为另外一种格式。当须要打印变量的值时,只需提供一种规格,指示 printf 如何打印信息(一般包含在双引号中)便可。必须为每一个传递到 printf 的变量包含一个规格参数;若是包含过少的参数,则 printf 不会打印全部的数值。 

处理错误 

AWK 工具报告所发生错误的方式很使人恼火。一个错误会阻碍任何操做的进行,所提供的错误信息很是含混不清: 

awk: syntax error near line 2 
awk: bailing out near line 2 

您可能会花几小时的时间查看第 2 行,试图找出它为何阻碍程序运行;这就是支持使用源文件的一个有力论据。 

切记有两条规则能够帮助您避免出现语法错误: 

1. 确保命令位于括号中,而括号位于单引号中。没有使用这些字符之一必然致使程序没法运行。 

2. 搜索命令须要位于斜线之间。要找出住在印第安那州的员工,您必须使用“/IN/”而不是“IN”。 

结论 

尽管 AWK 彻底表明另外的含意,但它应该是管理员智能工具包的首字母缩写。连同 SED 一块儿,AWK 实用工具是 Linux 管理员所拥有的功能最强大和灵活的工具之一。经过了解其语言的一些特性,您能够开辟出可以简化任务的领域,不然这些任务将会是很是费时和困难的
相关文章
相关标签/搜索
本站公众号
   欢迎关注本站公众号,获取更多信息