linux shell编程指南第九章------AWK 介绍3

本章开始已经提到过, a w k脚本大多只有一行,其中很少是字符串表示的。本书大多要求
在一行内完成a w k脚本,这一点通过将变量传入a w k命令行会变得很容易。现就其基本原理讲
述一些例子。

使用管道将字符串s t a n d - b y传入a w k,返回其长度。

[root@localhost huangcd]# echo "Stand-by"|awk '{print length($0)}'
8

设置文件名为一变量,管道输出到a w k,返回不带扩展名的文件名。

[root@localhost huangcd]# STR="gSSDFFDSW.txt"
[root@localhost huangcd]# echo $STR|awk '{print substr($STR,1,5)}'
gSSDF

设置文件名为一变量,管道输出到a w k,只返回其扩展名。

[root@localhost huangcd]# STR="mydoc.txt"
[root@localhost huangcd]# echo $STR|awk '{print substr($STR,7)}'
txt

使用字符串或正则表达式时,有时需要在输出中加入一新行或查询一元字符。
打印一新行时,(新行为字符\ n),给出其屏蔽序列,以不失其特殊含义,用法为在字符
串前加入反斜线。例如使用\ n强迫打印一新行。

如果使用正则表达式,查询花括号( { }),在字符前加反斜线,如/ \ { /,将在a w k中失掉其特殊含义。


使用上述符号,打印May Day,中间夹t a b键,后跟两个新行,再打印May Day,但这次
使用八进制数1 0 4、1 4 1、1 7 1、分别代表D、a、y。

[root@localhost huangcd]# awk 'BEGIN {print "\nMay\tDay\n\nMay\t \104\141\171"}'
 
May     Day


May      Day

注意,\ 1 0 4为D的八进制A S C I I码,\ 1 4 1为a的八进制A S C I I码,等等。

目前为止,所有例子的输出都是直接到屏幕,除了t a b键以外没有任何格式。a w k提供函
数p r i n t f,拥有几种不同的格式化输出功能。例如按列输出、左对齐或右对齐方式。
每一种p r i n t f函数(格式控制字符)都以一个%符号开始,以一个决定转换的字符结束。
转换包含三种修饰符。
p r i n t f函数基本语法是p r i n t f([格式控制符],参数),格式控制字符通常在引号里。


[root@localhost huangcd]# echo "65" |awk '{printf "%c\n",$0}'
A
[root@localhost huangcd]# awk 'BEGIN {printf "%c\n",65}'
A
[root@localhost huangcd]# awk 'BEGIN {printf "%f\n",999}'
999.000000

打印所有的学生名字和序列号,要求名字左对齐, 1 5个字符长度,后跟序列号。注意\ n
换行符放在最后一个指示符后面。输出将自动分成两列。

[root@localhost huangcd]# awk '{printf "%-15s %s\n",$1,$3}' grade.txt 
M.Tansley       48311
J.Lulu              48317
P.Bunny          48
J.Troll              4842
L.Tansley       4712

向一行a w k命令传值:

在查看a w k脚本前,先来查看怎样在a w k命令行中传递变量。
在a w k执行前将值传入a w k变量,需要将变量放在命令行中,格式如下:
awk 命令变量=输入文件值

(后面会讲到怎样传递变量到a w k脚本中)。
下面的例子在命令行中设置变量A G E等于1 0,然后传入a w k中,查询年龄在1 0岁以下的
所有学生。

[root@localhost huangcd]# awk '{if($5<AGE) print $0}' AGE=10 grade.txt 
M.Tansley   05/99     48311  Green    8    40   44
J.Lulu      06/99     48317  green    9    24   26

要快速查看文件系统空间容量,观察其是否达到一定水平,可使用下面a w k一行脚本。因
为要监视的已使用空间容量不断在变化,可以在命令行指定一个触发值。首先用管道命令将
df -k 传入a w k,然后抽出第4列,即剩余可利用空间容量。使用$ 4 ~ / ^ [ 0 - 9 ] /取得容量数值
(1 0 2 4块)而不是d f的文件头,然后对命令行与‘ i f ( $ 4 < T R I G G E R )’上变量T R I G G E R中指定
的值进行查询测试。

[root@localhost huangcd]# df -k|awk '($4~/^[0-9]/) {if($4<TRIGGER) print $6"\t"$4}' TRIGGER=560000
/dev/shm        517276

当然可以使用管道将值传入a w k。本例使用w h o命令, w h o命令第一列包含注册用户名,
这里打印注册用户,并加入一定信息。

[root@localhost huangcd]# who|awk '{print $1 " is logged on"}'
root is logged on
root is logged on

a w k也允许传入环境变量。下面的例子使用环境变量L O G N A M E支持当前用户名。可从
w h o命令管道输出到a w k中获得相应信息。

[root@localhost huangcd]# who|awk '{if($1==user) print $1" you are connected to " $2}'user=$LOGNAME


awk脚本文件:

可以将a w k脚本写入一个文件再执行它。命令不必很长(尽管这是写入一个脚本文件的主
要原因),甚至可以接受一行命令。这样可以保存a w k命令,以使不必每次使用时都需要重新
输入。使用文件的另一个好处是可以增加注释,以便于理解脚本的真正用途和功能。
使用前面的几个例子,将之转换成a w k可执行文件。像原来做的一样,将学生目前级别分
相加awk ‘(t o t + = $ 6) END{print "club student total points:" t o t }’ g r a d e . t x t。
创建新文件s t u d e n t t o t . a w k,给所有a w k程序加入a w k扩展名是一种好习惯,这样通过查
看文件名就知道这是一个a w k程序。文本如下:

[root@localhost huangcd]# cat student_tot.awk 
#!/bin/awk -f
BEGIN{print "Student    Date  Member No.  Grade  Age Points Max"
 print "Name       Joined                       Gained Point Available"
 print "=============================================================="
}

(tot+=$6)

END{print "Club student total points :"tot
    print "Average Club Student points:" tot/NR}

第一行是#!/bin/awk -f。这很重要,没有它自包含脚本将不能执行。这一行告之脚本系统
中a w k的位置。通过将命令分开,脚本可读性提高,还可以在命令之间加入注释。这里加入头
信息和结尾的平均值。基本上这是一个一行脚本文件。
执行时,在脚本文件后键入输入文件名,但是首先要对脚本文件加入可执行权限。

[root@localhost huangcd]# ./student_tot.awk  grade.txt 
Student    Date  Member No.  Grade  Age Points Max
Name       Joined                       Gained Point Available
==============================================================
M.Tansley   05/99     48311  Green    8    40   44
J.Lulu      06/99     48317  green    9    24   26
P.Bunny     02/99     48     Yellow   12   35   28
J.Troll     07/99     4842   Brown-3  12   26   26
L.Tansley   05/99     4712   Brown-2  12   30   28
Club student total points :155
Average Club Student points:31

在a w k中使用F S变量:

如果使用非空格符做域分隔符( F S)浏览文件,例如# 或:,编写这样的一行命令很容易,
因为使用F S选项可以在命令行中指定域分隔符。

awk    -f    :   ' awk   {print   $0} '     input-file

使用a w k脚本时,记住设置F S变量是在B E G I N部分。如果不这样做, a w k将会发生混淆,
不知道域分隔符是什么。
下述脚本指定F S变量。脚本从/ e t c / p a s s w d文件中抽取第1和第5域,通过分号“;”分隔
p a s s w d文件域。第1域是帐号名,第5域是帐号所有者。
[root@localhost huangcd]# cat passwd.awk
#!/bin/awk -f
BEGIN{
FS=":"}
{print $1,"\t",$5}
[root@localhost huangcd]# ./passwd.awk /etc/passwd
root     root
bin      bin
daemon   daemon
adm      adm
lp       lp
sync     sync

向a w k脚本传值与向a w k一行命令传值方式大体相同,格式为:
awk script_file var=value input_file
下述脚本对比检查文件中域号和指定数字。这里使用了N F变量M A X,表示指定检查的域
号,使用双引号将域分隔符括起来,即使它是一个空格。

[root@localhost huangcd]# cat fieldcheck 
#!/bin/awk -f
NF!=MAX{
print("line " NR" does not have "MAX" fields")}
[root@localhost huangcd]# ./fieldcheck MAX=7 FS=":"  /etc/passwd
[root@localhost huangcd]# ./fieldcheck MAX=8 FS=":"  /etc/passwd
line 1 does not have 8 fields
line 2 does not have 8 fields
line 3 does not have 8 fields
line 4 does not have 8 fields

[root@localhost huangcd]# cat name.awk 
#!/bin/awk -f
{if($5<AGE) print $0}
[root@localhost huangcd]# ./name.awk AGE=10 grade.txt 
M.Tansley   05/99     48311  Green    8    40   44
J.Lulu      06/99     48317  green    9    24   26

同样可以使用前面提到的管道命令传值,下述a w k脚本从d u命令获得输入,并输出块和字节数。

[root@localhost huangcd]# cat duawk.awk 
#!/bin/awk -f
BEGIN{
OFS="\t";
print "name" "\t\t","bytes","blocks\n"
print "=============================="}
{print $2,"\t\t",$1*512,$1}
[root@localhost huangcd]# du|./duawk.awk |less

name                    bytes   blocks


==============================
./.gnome2/file-roller                           4096    8
./.gnome2/accels                                8192    16
./.gnome2/nautilus-scripts                              4096    8
./.gnome2/share/fonts                           8192    16
./.gnome2/share/cursor-fonts                            8192    16

awk数组:

数组使用前,不必定义,也不必指定数组元素个数。经常使用循环来访问数组。下面是
一种循环类型的基本结构:
For (element in array ) print array[element]
对于记录“ 1 2 3 # 4 5 6 # 6 7 8”,先使用s p l i t函数划分它,再使用循环打印各数组元素。操作
脚本如下:

要运行脚本,使用/ d e v / n u l l作为输入文件。

[root@localhost huangcd]# cat arraytest.awk 
#!/bin/awk -f
BEGIN{
record="123#456#789";
split(record,myarray,"#")}
END{for(i in myarray)
    {print myarray[i]}}
[root@localhost huangcd]# ./arraytest.awk /dev/null
123
456
789

a w k语言学起来可能有些复杂,但使用它来编写一行命令或小脚本并不太难。本章讲述了
a w k的最基本功能,相信大家已经掌握了a w k的基本用法。a w k是s h e l l编程的一个重要工具。
在s h e l l命令或编程中,虽然可以使用a w k强大的文本处理能力,但是并不要求你成为这方面的
专家。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值