awk提取命令详解

本文出自http://hi.baidu.com/cjy2020/blog/item/b18c0587a0476026c65cc3c7.html,感受很好,因此转载收藏

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:DULA NEY:EVAN:M OBILE:AL
46013:DURH AM:JEFF:MO BILE:AL
46015:STEE N:BILL:MOB ILE:AL
46017:FELD MAN:EVAN:M OBILE:AL
46018:SWIM :STEVE:UNK NOWN:AL
46019:BOGU E:ROBERT:P HOENIX:AZ
46021:JUNE :MICAH:PHO ENIX:AZ
46022:KANE :SHERYL:UN KNOWN:AR
46024:WOOD :WILLIAM:M UNCIE:IN
46026:FERG US:SARAH:M UNCIE:IN
46027:BUCK :SARAH:MUN CIE:IN
46029:TUTT LE:BOB:MUN CIE: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-DULA NEY-EVAN-M OBILE-AL
46013-DURH AM-JEFF-MO BILE-AL
46015-STEE N-BILL-MOB ILE-AL
46017-FELD MAN-EVAN-M OBILE-AL
46018-SWIM -STEVE-UNK NOWN-AL
46019-BOGU E-ROBERT-P HOENIX-AZ
46021-JUNE -MICAH-PHO ENIX-AZ
46022-KANE -SHERYL-UN KNOWN-AR
46024-WOOD -WILLIAM-M UNCIE-IN
46026-FERG US-SARAH-M UNCIE-IN
46027-BUCK -SARAH-MUN CIE-IN
46029-TUTT LE-BOB-MUN CIE-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_na mes

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

$ 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
5
7
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,"BA L: "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 语句能够分别指定在处 理实际开始以前或者完 成以后进行操做。BE GIN 语句最经常使用于创建变量 或显示标题。另外一方面 ,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。该过程容许 您在离开所选定字段前 对文件执行其余操做。

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

$ awk '{print NR, $1 ) > "/tmp/file z" }' 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 管理员所拥有的功能最 强大和灵活的工具之一 。经过了解其语言的一 些特性,您能够开辟出 可以简化任务的领域, 不然这些任务将会是非 常费时和困难的。
相关文章
相关标签/搜索