红联Linux门户
Linux帮助

AWK:Linux管理员的智能工具包(三)

发布时间:2005-09-10 23:37:38来源:红联作者:aini
因此,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
$

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

共有 1 条评论

  1. aini 于 2005-09-10 23:38:13发表:

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

    $ cat awklist
    {print $3,$2}
    {print $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

    $

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

      如果简单的输出不能处理您的程序中所需要的复杂信息,则可以尝试由 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 管理员所拥有的功能最强大和灵活的工具之一。通过了解其语言的一些特性,您可以开辟出能够简化任务的领域,否则这些任务将会是非常费时和困难的。