shell脚本之awk学习笔记

来源:岁月联盟 编辑:exp 时间:2011-09-30

shell脚本学习笔记九——awk
    
#cat grade.txt
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

awk '{print $1,$4}' grade.txt
打印报告头
awk 'BEGIN {print "Name /t   Belt/n--------------------"}{print $1"/t"$4}' grade.txt
 
打印信息尾
# awk 'BEGIN{print "Name /t /n------"}{print $1}END{print "--end of report--"}' grade.txt

Name    
------
M.Tansley
J.Lulu
P.Bunny
J.Troll
L.Tansley
--end of report--

awk中正则表达式及其操作
1) 元字符     / ^ $ . [] | () * + ?
2) 条件操作符 <  <=  ==  !=  >=    ~ 匹配正则表达式   !~ 不匹配正则

表达式       

匹配  使一域号匹配正则表达式,使用 ‘~’后紧跟正则表达式,也可以使用

if语句.awk中if后面的条件用()括起来
# awk '{if($4 ~/Brown/)print $0}' grade.txt
J.Troll      07/99    4842    Brown-3  12   26   26
L.Tansley    05/99    4712    Brown-2  12   30   28
# awk '$0 ~/Brown/' grade.txt
J.Troll      07/99    4842    Brown-3  12   26   26
L.Tansley    05/99    4712    Brown-2  12   30   28

精确匹配
# awk '{if($3=="48") print $0}' grade.txt              第三列有很多

48,所以要用精确匹配
P.Bunny      02/99    48      Yellow   12   35   28
# awk '$3==48' grade.txt                               awk默认动作是

print
P.Bunny      02/99    48      Yellow   12   35   28

awk '{ if ($6 < $7) print $1" Try better at..."}' grade.txt
M.Tansley Try better at...
J.Lulu Try better at...

设置大小写     [] 可匹配任意字符或单词
awk '{if($4 ~/[Gg]reen/) print $0}' grade.txt
M.Tansley    05/99    48311   Green    8    40   44
J.Lulu       06/99    48317   green    9    24   26
awk '/[Gg]reen/' grade.txt         结果同上

任意字符
[root@localhost awk_sed]# awk '$1 ~/^...a/' grade.txt
M.Tansley    05/99    48311   Green    8    40   44
L.Tansley    05/99    4712    Brown-2  12   30   28
awk '{if(/^...a/) print}' grade.txt 结果同上

或关系匹配 | 匹配两边模式之一        使用竖线符时,语句必须用圆括号

括起来
# awk '$4 ~/([Yy]ellow|[Bb]rown)/' grade.txt   抽取级别为yellow或

brown的记录
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

行首
# awk '/^48/' grade.txt
# awk '/^P.B/' grade.txt
P.Bunny      02/99    48      Yellow   12   35   28
所有表达式(除字符重复出现外)在awk中都是合法的。
复合模式   &&  || !
# awk '{if($1=="P.Bunny" && $4=="Yellow") print $0}' grade.txt
P.Bunny      02/99    48      Yellow   12   35   28
awk '{if($4=="green" || $4 ~/Brown/) print $0}' grade.txt
J.Lulu       06/99    48317   green    9    24   26
J.Troll      07/99    4842    Brown-3  12   26   26
L.Tansley    05/99    4712    Brown-2  12   30   28

awk内置变量
ARGC      命令行参数个数
ARGV      命令行参数排列         ARGV[n]表示每一元素,n为期望访问的

命令行参数
ENVIRON   支持队列中系统环境变量的使用
FILENAME  awk浏览的文件名        awk可以同时处理许多文件
FNR       浏览文件的记录数
FS        设置输入域分隔符,等价于命令行-F选项。如果用逗号作域分隔符

,设置 FS=","
NF        浏览记录的域个数
NR        已读的记录数
OFS       输出域分隔符    缺省为空格。若想设置为#,写入OFS="#"
ORS       输出记录分隔符  缺省为新行(/n)
RS        控制记录分隔符  缺省为新行(/n)
下面为awk内置变量的例子
NR 快速查看记录个数,比如导出数据库文件后,要快速浏览记录个数。
# awk 'END{print NR}' grade.txt
5
# awk '{print NR}' grade.txt
1
2
3
4
5
#awk '{print NF,NR,$0}END{print FILENAME}' grade.txt  打印所有学生的

记录,并打印记录号及域个数(NF),文件名
7 1 M.Tansley    05/99    48311   Green    8    40   44
7 2 J.Lulu       06/99    48317   green    9    24   26
7 3 P.Bunny      02/99    48      Yellow   12   35   28
7 4 J.Troll      07/99    4842    Brown-3  12   26   26
7 5 L.Tansley    05/99    4712    Brown-2  12   30   28
grade.txt
在抽取信息时,最好先检查文件中是否有记录。
# awk '{if(NR>0 && $4 ~/Brown/)print $0}' grade.txt
J.Troll      07/99    4842    Brown-3  12   26   26
L.Tansley    05/99    4712    Brown-2  12   30   28
NF 的一个强大功能是将变量$PWD的返回值传入awk并显示其目录。这里需要指

定域分隔符
# echo $PWD | awk -F/ '{print $NF}'
awk_sed
echo "/usr/local/src" | awk -F/ '{print $NF}'  显示文件名
src

awk操作符
在awk中使用操作符,基本表达式分为划分数字型,字符串型,变量型,域及

数组元素
= += *= 、 = %= ^=    赋值操作符
?                          条件表达操作符
||  &&  !                  并,与,非
- !-                       匹配操作符,包括匹配和不匹配
< <= == != >>              关系操作符
+ - * / % ^                算术操作符
++ --                      前缀和后缀
1.设置输入域到域变量名
# awk '{name=$1;belts=$4; if(belts ~/Yellow/)print name"is belt"

belts'} grade.txt
P.Bunnyis beltYellow
2域值比较操作
两种方法:1.在BEGIN中给变量名赋值   2.在关系操作中使用实际数值。
用引号将数字引起来是可选的,“27”和27是一样的!
[root@localhost awk_sed]# awk '{if($6<27)print $0}' grade.txt
J.Lulu       06/99    48317   green    9    24   26
J.Troll      07/99    4842    Brown-3  12   26   26
# awk 'BEGIN {BASELINE="27"}{if($6<27) print $0}' grade.txt
J.Lulu       06/99    48317   green    9    24   26
J.Troll      07/99    4842    Brown-3  12   26   26
3. 修改数值域取值
awk修改任何域时,重要的一点是要记住实际输入文件是不可修改的,修改的

只是保存在缓存里的awk副本。awk会在变量NR或NF变量中反映出修改痕迹0。
awk '{if ($1=="M.Tansley") $6=$6-1;print $1 "/t" $6 "/t" $7}'

grade.txt
M.Tansley       39      44
J.Lulu  24      26
P.Bunny 35      28
J.Troll 26      26
L.Tansley       30      28
4. 修改文本域
awk '{if($1=="J.Troll") $1=="J.L.Troll";print $1}' grade.txt
M.Tansley
J.Lulu
P.Bunny
J.Troll
L.Tansley
5.只显示修改记录  在模式后面使用花括号将只打印修改部分
awk '{if($1=="J.Troll") {$1=="J.L.Troll";print $1}}' grade.txt
J.Troll
6.创建新的输出域

作者“it职业生涯”