智能驱动工具包:AWK:Linux 管理员的智能工具包

=italicbodycopy>作者 Emmett Dulaney =boldbodycopy>您正在学习 Linux 吗?本文对于非常有用 AWK 文本操作工具进行了介绍非常有价值

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

=parahead1>AWK 是什么?

=bodycopy>最简单地说AWK 是种用于处理文本编程语言工具AWK 实用工具语言在很多方面类似于 shell 编程语言尽管 AWK 具有完全属于其本身语法在最初创造 AWK 时其目是用于文本处理并且这种语言基础是只要在输入数据中有模式匹配就执行系列指令该实用工具扫描文件中查找和命令行中所给定内容相匹配模式如果发现匹配内容则进行下个编程步骤如果找不到匹配内容则继续处理下

=bodycopy>尽管操作可能会很复杂但命令语法始终是:

awk '{pattern + action}' {filenames}



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

=parahead1>了解字段

=bodycopy>实用工具将每个输入行分为记录和字段=italicbodycopy>记录=bodycopy>是单行输入而每条记录包含若干字段默认字段分隔符是空格或制表符而记录分隔符是换行虽然在默认情况下将制表符和空格都看作字段分隔符(多个空格仍然作为个分隔符)但是可以将分隔符从空格改为任何其它

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



=bodycopy>当 AWK 读取输入内容时整条记录被分配给变量 $0=bodycopy>每个字段以字段分隔符分开被分配给变量 $1、$2、$3=bodycopy> 等等行在本质上可以包含无数个字段通过字段号来访问每个字段因此命令

awk '{pr $1,$2,$3,$4,$5}' names



=bodycopy>将会产生打印输出是

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



=bodycopy>值得注意项重要内容是AWK 解释由空格分隔 5个字段但当它打印显示内容时在每个字段间只有个空格利用为每个字段指定了唯号码功能您可以选择只打印特定字段例如只打印每条记录姓名时只需选择第 2个和第 3个字段进行打印:

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



=bodycopy>您还可以指定按任何顺序打印字段而无论它们在记录中是如何存在因此只需要显示姓名字段并且使其顺序颠倒先显示名字再显示姓氏:

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



=parahead1>使用模式

=bodycopy>通过包含个必须匹配模式您可以选择只对特定记录而不是所有记录进行操作模式匹配最简单形式是搜索其中要匹配项目被包含在斜线 (/pattern/=bodycopy>) 中例如只对那些居住在阿拉巴马州员工执行前面操作:

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



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

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



=bodycopy>对同数据集多个命令可以用分号 (;=bodycopy>) 分隔开例如行中打印姓名而在另行中打印城市和州名:

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



=bodycopy>如果没有使用分号 (pr $3,$2,$4,$5=bodycopy>)则会在同行中显示所有内容方面如果分别给出两个打印语句则会产生完全区别结果:

$ awk '/AL/ {pr $3,$2} {pr $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 $



=bodycopy>只有在列表中找到 AL=bodycopy> 时才会给出字段 3和字段 2但是字段 4和字段 5是无条件始终打印它们只有第组花括号中命令对前面紧邻命令 (/AL/=bodycopy>) 起作用

=bodycopy>结果非常不便于阅读可以使其稍微更清晰首先在城市和州的间插入个空格和逗号然后在每两行显示的后放置个空行:

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



=bodycopy>在第 4和第 5个字段的间添加个逗号和个空格(在引号的间)在第 5个字段后面打印个换行符 (\n=bodycopy>)在 AWK 打印语句中还可以使用那些可在 echo=bodycopy> 命令中使用所有特殊包括:

  • \n=bodycopy>(换行)
  • \t=bodycopy>(制表)
  • \b=bodycopy>(退格)
  • \f=bodycopy>(进纸)
  • \r=bodycopy>(回车)


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

$ awk '{pr $1"\t"$2"\t"$3"\t"$4"\t"$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 $



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

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



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

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



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

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



=bodycopy>代字号(表示匹配)对应符号是个前面带有感叹号代字号 (!˜)这些通知如果搜索序列没有出现在指定字段中则找出和搜索序列相匹配所有行:

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



=bodycopy>在这种情况下将显示第 5个字段中没有 AR 所有行 — 包括两个 Sarah 条目这两个条目确实包含 AR但却是在第 3个字段而不是第 5个字段中

=parahead1>花括号和字段分隔符

=bodycopy>括号在 AWK 命令中起着很重要作用出现在括号的间操作指出将要发生什么以及何时发生当只使用对括号时:

{pr $3,$2}



=bodycopy>括号间所有操作同时发生当使用多于括号时:

{pr $3}{pr $2}



=bodycopy>执行第组命令在该命令完成后执行第 2组命令注意以下两列清单区别:

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



=bodycopy>要利用多组括号进行重复查找执行第组中命令直到完成为止;然后处理第 2组命令如果有第 3组命令则在第 2组命令完成后执行它以此类推在所生成打印输出中有两个分隔打印命令因此先执行第个命令随后执行第 2个命令这样导致每个条目显示在两行而不是行中

=bodycopy>区分两个字段字段分隔符不定始终是空格;它可以是任何可识别为进行演示假定 emp_names=bodycopy> 文件利用冒号而不是制表符来分隔字段:

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



=bodycopy>如果试图通过指定所需要第 2个字段来打印姓氏

$ awk '{pr $2}' emp_names



=bodycopy>您最后会得到十 2个空行文件中没有空格除了第个字段的外没有可认别字段为解决这问题必须通知 AWK 是空格的外作为分隔符有两种思路方法可通知 AWK 使用新字段分隔符:使用命令行参数 -F=bodycopy>或在中指定变量 FS两种思路方法效果相同只有种例外情况如下例所示:

$ awk '{FS=":"}{pr $2}' emp_names DURHAM STEEN FELDMAN SWIM BOGUE JUNE KANE WOOD FERGUS BUCK TUTTLE $ $ awk -F: '{pr $2}' emp_names DULANEY DURHAM STEEN FELDMAN SWIM BOGUE JUNE KANE WOOD FERGUS BUCK TUTTLE $



=bodycopy>在第个命令中条记录返回不正确空行而其他结果正确直到读取第 2条记录时才识别字段分隔符并正确地执行通过使用 BEGIN=bodycopy> 语句可以纠正这缺点(在后文详述)-F=bodycopy> 功能非常类似于 BEGIN=bodycopy>能够正确地读取第条记录并按要求执行

=bodycopy>在本文开始处我曾提到默认显示/输出字段分隔符是空格通过使用输出字段分隔符 (OFS=bodycopy>) 变量可以在中更改此特性例如要读取文件(由冒号分隔)并以短划线显示则命令是

$ awk -F":" '{OFS="-"}{pr $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 =bodycopy>和 OFS=bodycopy> 是(输入)字段分隔符和输出字段分隔符它们只是对可以在 AWK 实用工具中使用变量例如要在打印时为每行编号可以采用以下方式使用 NR=bodycopy> 变量:

$ awk -F":" '{pr 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 $



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

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



=parahead1>添加文本

=bodycopy>可以按照添加控制序列或其他相同方式将文本添加到显示中例如要将分隔符从空格改为冒号则命令是

awk '{pr $1":"$2":"$3":"$4":"$5}' emp_names > _emp_names



=bodycopy>在这种情况下 (:=bodycopy>) 包含在引号 ("/"=bodycopy>) 中它被添加到每个字段的间在引号的间值可以是任何内容例如创建个有关居住在阿拉巴马州员工外观类似数据库显示:

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



=parahead1>数学操作

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

+ =bodycopy>将数字相加
- =bodycopy>减
* =bodycopy>乘
/ =bodycopy>除
^ =bodycopy>执行指数运算
% =bodycopy>提供模
=bodycopy>将变量值加
=bodycopy>将其他操作结果分配给变量
=bodycopy>将变量减
-= =bodycopy>将减法操作结果分配给变量
*= =bodycopy>分配乘法操作结果
/= =bodycopy>分配除法操作结果
%= =bodycopy>分配求模操作结果

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

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



=bodycopy>第项业务定单是通过将第 2个字段(数量)值乘以第 3个字段(价格)计算每种物品库存价值:

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



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

$ awk '{x=x+$2} {pr x}' inventory 5 7 14 16 71 194 994 1074 1174 $



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

=bodycopy>可以应用相同过程来确定现有库存总价值:

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



=bodycopy>因此1174 件物品价值是 $2,241.66虽然这过程可以获得总计值但它外观很差需要加工成实际报表利用些附加项很容易使显示变得更整洁:

$ awk '{x=x+($2*$3)}{pr $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 drts 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 $



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

BEGIN=bodycopy> 和 END

=bodycopy>使用 BEGIN=bodycopy> 和 END=bodycopy> 语句可以分别指定在处理实际开始的前或者完成的后进行操作BEGIN=bodycopy> 语句最常用于建立变量或显示标题方面END=bodycopy> 语句可用于在结束后继续进行处理

=bodycopy>在前面举例中利用以下例程生成了物品总价值:

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



=bodycopy>该例程在运行总计累加时显示了文件中没有其他思路方法可以指定它而不让在每行进行打印也导致它始终不打印出来但是利用 END=bodycopy> 语句可以避免这问题:

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



=bodycopy>定义了变量 x=bodycopy>它对每行进行处理;但是在所有处理完成的前不会生成显示尽管可以作为独立例程使用它也可以置入到先前代码列表添加更多信息并生成更完整报表:

$ awk '{x=x+($2*$3)} {pr $1,"QTY: "$2,"PRICE: "$3,"TOTAL: "$2*$3} END {pr "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 drts 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 $



=bodycopy>BEGIN=bodycopy> 命令和 END=bodycopy> 工作方式相同但它建立了那些需要在完成其他工作的前所做项目该过程最常见是创建报表标题此例程语法类似于

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



=parahead1>输入、输出和源文件

=bodycopy>AWK 工具可以从文件中读取其输入正如在此的前所有举例所做那样它也可以从其他命令输出中获取输入例如:

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



=bodycopy>awk=bodycopy> 命令输入是排序操作输出除了 sort=bodycopy>还可以使用任何其他 Linux 命令 — 例如 grep=bodycopy>该过程允许您在离开所选定字段前对文件执行其他操作

=bodycopy>类似于解释AWK 使用输出改向操作符 >=bodycopy> 和 >>=bodycopy> 将其输出放入文件中而不是标准输出设备这些符号作用类似于它们在解释对应符号因此 >=bodycopy> 在不存在文件时创建文件>>=bodycopy> 追加到现有文件尾部请看以下举例:

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



=bodycopy>检查该语句语法您会看到输出改向是在打印语句完成后进行必须将文件名包含在引号中否则它只是个未 AWK 变量而将指令联接起来会在 AWK 中产生(如果不正确地使用改向符号则 AWK 无法了解该符号意味着“改向”还是个关系操作符)

=bodycopy>在 AWK 中输出到管道也类似于解释中所实现相同操作要将打印命令输出发送到管道中可以在打印命令后附加管道符号以及命令名称如下所示:

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



=bodycopy>这是输出改向情况必须将命令包含在引号中而管道名称是被执行命令名称

=bodycopy>AWK 所使用命令可以来自两个地方首先可以在命令行中指定它们如举例中所示其次它们可以由源文件提供如果是这种情况通过 -f=bodycopy> 选项将这种情况向 AWK 发出警告演示如下:

$ cat awklist {pr $3,$2} {pr $4,$5,"\n"} $ $ 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 $



=bodycopy>注意在源文件中任何地方或者在命令行中它时不使用单引号单引号只用于区别命令行中命令和文件名称

=bodycopy>如果简单输出不能处理您中所需要复杂信息则可以尝试由 prf=bodycopy> 命令获得更加复杂输出其语法是

prf( format, value, value ...)



=bodycopy>该语法类似于 C 语言中 prf=bodycopy> 命令而格式规格是相同通过插入项定义如何打印数值规格可以定义该格式格式规格包含个跟有字母 %类似于打印命令prf=bodycopy> 不必包含在圆括号中但是可以认为使用圆括号是种良好习惯

=bodycopy>下表列出 prf=bodycopy> 命令提供各种规格

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






=bodycopy>可以在 % 和的间提供某些附加格式化参数这些参数进步改进数值打印方式:

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





=bodycopy>prf=bodycopy> 命令能够控制并将数值从种格式转换为另种格式当需要打印变量值时只需提供种规格指示 prf=bodycopy> 如何打印信息(通常包含在双引号中)即可必须为每个传递到 prf=bodycopy> 变量包含个规格参数;如果包含过少参数prf=bodycopy> 不会打印所有数值

=parahead1>处理

=bodycopy>AWK 工具报告所发生方式很令人恼火会阻碍任何操作进行所提供信息非常含混不清:

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



=bodycopy>您可能会花几小时时间查看第 2 行试图找出它为什么阻碍运行;这就是支持使用源文件个有力论据
=parahead1>接下来步骤


=bodycopy>阅读 =bodylink>Linux 平台上 Oracle 常见问题解答

=bodycopy> =bodycopy>访问并收藏=bodylink> Linux 技术中心

=bodycopy> =bodycopy>阅读 Dale Dougherty 和 Arnold Robbins 著作 =bodylink>sed & awk, 2nd Edition(O'Reilly & Associates 出版社)






=bodycopy>切记有两条规则可以帮助您避免出现语法:

=bodycopy>1. 确保命令位于括号中而括号位于单引号中没有使用这些必然导致无法运行

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

=parahead1>结论

=bodycopy>尽管 AWK 完全代表另外含意但它应该是管理员智能工具包首字母缩写连同 SED AWK 实用工具是 Linux 管理员所拥有功能最强大和灵活工具的通过了解其语言些特性您可以开辟出能够简化任务领域否则这些任务将会是非常费时和困难




=boldbodycopy>Emmett Dulaney=bodycopy> (=bodylink>[email protected]) 获得了 18 种供应商认证他编写了数本有关 Linux、UNIX 和认证研究书籍并在许多会议上进行了演讲而且他是 Mercury Technical Solutions 前合作伙伴
Tags:  黑客工具包 工具包 啊d网络工具包 智能驱动工具包

延伸阅读

最新评论

发表评论