linux shell编程指南第九章------AWK 介绍2
2013-11-27 23:54
453 查看
修改文本域即对其重新赋值。需要做的就是赋给一个新的字符串。在J . Tr o l l中加入字母,
使其成为J . L . Tr o l l,表达式为$ 1 = " J . L . Tr o l l ",记住字符串要使用双秒号( " "),并用圆括号括
起整个语法。
root@localhost huangcd]# awk '{if($1=="J.Troll") ($1="J.L.Troll"); print $1}' grade.txt
M.Tansley
J.Lulu
P.Bunny
J.L.Troll
L.Tansley
但如果文件很大,记录甚至超过1 0 0,打印所有记录只为查看修改部分显然不合情理。在模式
后面使用花括号将只打印修改部分。
[root@localhost huangcd]# awk '{if($1=="J.Troll") ($1="J.L.Troll");print $1}' grade.txt
M.Tansley
J.Lulu
P.Bunny
J.L.Troll
L.Tansley
在a w k中处理数据时,基于各域进行计算时创建新域是一种好习惯。创建新域要通过其他
域赋予新域标识符。如创建一个基于其他域的加法新域{ $ 4 = $ 2 + $ 3 },这里假定记录包含3个域,
则域4为新建域,保存域2和域3相加结果。
在文件g r a d e . t x t中创建新域8保存域目前级别分与域最高级别分的减法值。表达式为
‘{ $ 8 = $ 7 - $ 6 }’,语法首先测试域目前级别分小于域最高级别分。新域因此只打印其值大于零
的学生名称及其新域值。在B E G I N部分加入t a b键以对齐报告头。
[root@localhost huangcd]# awk 'BEGIN{print "Name\t Difference"} {if($6<$7){$8=$7-$6;print $1,$8}}' grade.txt
Name Difference
M.Tansley 4
J.Lulu 2
当然可以创建新域,并赋给其更有意义的变量名。例如:
[root@localhost huangcd]# awk 'BEGIN{print "Name\t Difference"} {if($6<$7){diff=$7-$6;print $1,diff}}' grade.txt
Name Difference
M.Tansley 4
J.Lulu 2
为增加列数或进行运行结果统计,使用符号+ =。增加的结果赋给符号左边变量值,增加
到变量的域在符号右边。例如将$ 1加入变量t o t a l,表达式为t o t a l + = $ 1。列值增加很有用。许
多文件都要求统计总数,但输出其统计结果十分繁琐。在a w k中这很简单,请看下面的例子。
将所有学生的‘目前级别分’加在一起,方法是t o t + = $ 6,t o t即为a w k浏览的整个文件的
域6结果总和。所有记录读完后,在E N D部分加入一些提示信息及域6总和。不必在a w k中显
示说明打印所有记录,每一个操作匹配时,这是缺省动作。
[root@localhost huangcd]# awk '(tot+=$6);END{print "Club student total points:"tot}' 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
Club student total points:155
如果文件很大,你只想打印结果部分而不是所有记录,在语句的外面加上圆括号{}即可。
[root@localhost huangcd]# awk '{(tot+=$6)};END{print "Club student total points:"tot}' grade.txt
Club student total points:155
文件长度相加:
在目录中查看文件时,如果想快速查看所有文件的长度及其总和,但要排除子目录,使
用ls -l命令,然后管道输出到a w k,a w k首先剔除首字符为d(使用正则表达式)的记录,然后
将文件长度列相加,并输出每一文件长度及在E N D部分输出所有文件的长度。
下面的正则表达式表明必须匹配行首,并排除字符d,表达式为^ [ ^ d ]。
使用此模式打印文件名及其长度,然后将各长度相加放入变量t o t中。
[root@localhost huangcd]# ls -l |awk '/^[^d]/ {print $8"\t"$5} {tot+=$5} END{print "total KB:"tot}'
addaccount.sh 179
data.f 302
delete_me_and_die 255
file1 0
files.out 464
filetest 46
find.dt 423
grade.txt 255
grep.err 0
huangcdcron 55
myfile1.txt 20
myfile.txt 82
nltk-2.0.4.tar.gz 955978
nohup.out 0
PyYAML-3.10.tar.gz 241524
qrt.tmp 0
sort.out 323
var_text.sh 114
who.out 85
wow 255
total KB:1233128
g s u b函数有点类似于s e d查找和替换。它允许替换一个字符串或字符为另一个字符串或字
符,并以正则表达式的形式执行。第一个函数作用于记录$ 0,第二个g s u b函数允许指定目标,
然而,如果未指定目标,缺省为$ 0。
i n d e x(s,t)函数返回目标字符串s中查询字符串t的首位置。l e n g t h函数返回字符串s字符
长度。m a t c h函数测试字符串s是否包含一个正则表达式r定义的匹配。s p l i t使用域分隔符f s将
字符串s划分为指定序列a。s p r i n t函数类似于p r i n t f函数(以后涉及),返回基本输出格式f m t的
结果字符串e x p。s u b(r,s)函数将用s替代$ 0中最左边最长的子串,该子串被( r)匹配。
s u b(s,p)返回字符串s在位置p后的后缀。s u b s t r(s,p,n)同上,并指定子串长度为n。
要在整个记录中替换一个字符串为另一个,使用正则表达式格式, /目标模式/,替换模式
/。例如改变学生序号4 8 4 2到4 8 9 9:
[root@localhost huangcd]# awk 'gsub(/4842/,4899) {print $0} END{print "nihao"}' grade.txt
J.Troll 07/99 4899 Brown-3 12 26 26
nihao
查询字符串s中t出现的第一位置。必须用双引号将字符串括起来。例如返回目标字符串
B u n n y中n y出现的第一位置,即字符个数。
[root@localhost huangcd]# awk 'BEGIN {print index("Bunny","ny")}' grade.txt
4
返回所需字符串长度,例如检验字符串J . Tr o l l返回名字及其长度,即人名构成的字符个数。
[root@localhost huangcd]# awk '$1=="J.Troll" {print length($1)" "$1}' grade.txt
7 J.Troll
还有一种方法,这里字符串加双引号。
[root@localhost huangcd]# awk 'BEGIN {print length("nihao ma")}'
8
m a t c h测试目标字符串是否包含查找字符的一部分。可以对查找部分使用正则表达式,返
回值为成功出现的字符排列数。如果未找到,返回0,第一个例子在A N C D中查找d。因其不
存在,所以返回0。第二个例子在A N C D中查找D。因其存在,所以返回A N C D中D出现的首位
置字符数。第三个例子在学生J . L u l u中查找u。
[root@localhost huangcd]# awk 'BEGIN {print length("nihao ma")}'
8
[root@localhost huangcd]# awk 'BEGIN {print match("ANCD",/d/)}'
0
[root@localhost huangcd]# awk 'BEGIN {print match("ANCD",/C/)}'
3
[root@localhost huangcd]# awk '$1=="J.Lulu" {print match($1,"u")}' grade.txt
4
使用s p l i t返回字符串数组元素个数。工作方式如下:如果有一字符串,包含一指定分隔
符- ,例如A D2 - K P 9 - J U 2 - L P - 1,将之划分成一个数组。使用s p l i t,指定分隔符及数组名。此
例中,命令格式为( " A D 2 - K P 9 - J U 2 - L P - 1 ",p a r t s a r r a y," - "),s p l i t然后返回数组下标数,这
里结果为4。
[root@localhost huangcd]# awk 'BEGIN {print split("123#456#789",myarr,"#");print myarr[1],myarr[2],myarr[3]}'
3
123 456 789
这里myarr用于存储得到的数组。
本章使用s u b发现并替换模式的第一次出现位置。字符串S T R包含‘poped popo pill’,执行下
列s u b命令s u b(/ o p /," o p ",S T R)。模式o p第一次出现时,进行替换操作,返回结果如下:
‘pO Ped pope pill’。文本文件中,学生J . Tr o l l的记录有两个值一样,“目前级别分”与“最高级别分”。只
改变第一个为2 9,第二个仍为2 6不动,操作命令为s u b(/ 2 6 /," 2 9 ",$ 0),只替换第一个出现
2 4的位置。注意J . Tr o l l记录需存在。
[root@localhost huangcd]# awk '$1=="J.Troll" sub(/26/,"29",$0)' grade.txt
s u b s t r是一个很有用的函数。它按照起始位置及长度返回字符串的一部分。例子如下:
[root@localhost huangcd]# awk '$1=="L.Tansley" {print substr($1,1,5)}' grade.txt
L.Tan
上面例子中,指定在域1的第一个字符开始,返回其前面5个字符。
如果给定长度值远大于字符串长度, a w k将从起始位置返回所有字符,要抽取L Ta n s l - e y
的姓,只需从第3个字符开始返回长度为7。可以输入长度9 9,a w k返回结果相同。
[root@localhost huangcd]# awk '$1=="L.Tansley" {print substr($1,3,99)}' grade.txt
Tansley
s u b s t r的另一种形式是返回字符串后缀或指定位置后面字符。这里需要给出指定字符串及
其返回字串的起始位置。例如,从文本文件中抽取姓氏,需操作域1,并从第三个字符开始:
[root@localhost huangcd]# awk '{print substr($1,3,99)}' grade.txt Tansley
Lulu
Bunny
Troll
Tansley
使其成为J . L . Tr o l l,表达式为$ 1 = " J . L . Tr o l l ",记住字符串要使用双秒号( " "),并用圆括号括
起整个语法。
root@localhost huangcd]# awk '{if($1=="J.Troll") ($1="J.L.Troll"); print $1}' grade.txt
M.Tansley
J.Lulu
P.Bunny
J.L.Troll
L.Tansley
但如果文件很大,记录甚至超过1 0 0,打印所有记录只为查看修改部分显然不合情理。在模式
后面使用花括号将只打印修改部分。
[root@localhost huangcd]# awk '{if($1=="J.Troll") ($1="J.L.Troll");print $1}' grade.txt
M.Tansley
J.Lulu
P.Bunny
J.L.Troll
L.Tansley
在a w k中处理数据时,基于各域进行计算时创建新域是一种好习惯。创建新域要通过其他
域赋予新域标识符。如创建一个基于其他域的加法新域{ $ 4 = $ 2 + $ 3 },这里假定记录包含3个域,
则域4为新建域,保存域2和域3相加结果。
在文件g r a d e . t x t中创建新域8保存域目前级别分与域最高级别分的减法值。表达式为
‘{ $ 8 = $ 7 - $ 6 }’,语法首先测试域目前级别分小于域最高级别分。新域因此只打印其值大于零
的学生名称及其新域值。在B E G I N部分加入t a b键以对齐报告头。
[root@localhost huangcd]# awk 'BEGIN{print "Name\t Difference"} {if($6<$7){$8=$7-$6;print $1,$8}}' grade.txt
Name Difference
M.Tansley 4
J.Lulu 2
当然可以创建新域,并赋给其更有意义的变量名。例如:
[root@localhost huangcd]# awk 'BEGIN{print "Name\t Difference"} {if($6<$7){diff=$7-$6;print $1,diff}}' grade.txt
Name Difference
M.Tansley 4
J.Lulu 2
为增加列数或进行运行结果统计,使用符号+ =。增加的结果赋给符号左边变量值,增加
到变量的域在符号右边。例如将$ 1加入变量t o t a l,表达式为t o t a l + = $ 1。列值增加很有用。许
多文件都要求统计总数,但输出其统计结果十分繁琐。在a w k中这很简单,请看下面的例子。
将所有学生的‘目前级别分’加在一起,方法是t o t + = $ 6,t o t即为a w k浏览的整个文件的
域6结果总和。所有记录读完后,在E N D部分加入一些提示信息及域6总和。不必在a w k中显
示说明打印所有记录,每一个操作匹配时,这是缺省动作。
[root@localhost huangcd]# awk '(tot+=$6);END{print "Club student total points:"tot}' 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
Club student total points:155
如果文件很大,你只想打印结果部分而不是所有记录,在语句的外面加上圆括号{}即可。
[root@localhost huangcd]# awk '{(tot+=$6)};END{print "Club student total points:"tot}' grade.txt
Club student total points:155
文件长度相加:
在目录中查看文件时,如果想快速查看所有文件的长度及其总和,但要排除子目录,使
用ls -l命令,然后管道输出到a w k,a w k首先剔除首字符为d(使用正则表达式)的记录,然后
将文件长度列相加,并输出每一文件长度及在E N D部分输出所有文件的长度。
下面的正则表达式表明必须匹配行首,并排除字符d,表达式为^ [ ^ d ]。
使用此模式打印文件名及其长度,然后将各长度相加放入变量t o t中。
[root@localhost huangcd]# ls -l |awk '/^[^d]/ {print $8"\t"$5} {tot+=$5} END{print "total KB:"tot}'
addaccount.sh 179
data.f 302
delete_me_and_die 255
file1 0
files.out 464
filetest 46
find.dt 423
grade.txt 255
grep.err 0
huangcdcron 55
myfile1.txt 20
myfile.txt 82
nltk-2.0.4.tar.gz 955978
nohup.out 0
PyYAML-3.10.tar.gz 241524
qrt.tmp 0
sort.out 323
var_text.sh 114
who.out 85
wow 255
total KB:1233128
g s u b函数有点类似于s e d查找和替换。它允许替换一个字符串或字符为另一个字符串或字
符,并以正则表达式的形式执行。第一个函数作用于记录$ 0,第二个g s u b函数允许指定目标,
然而,如果未指定目标,缺省为$ 0。
i n d e x(s,t)函数返回目标字符串s中查询字符串t的首位置。l e n g t h函数返回字符串s字符
长度。m a t c h函数测试字符串s是否包含一个正则表达式r定义的匹配。s p l i t使用域分隔符f s将
字符串s划分为指定序列a。s p r i n t函数类似于p r i n t f函数(以后涉及),返回基本输出格式f m t的
结果字符串e x p。s u b(r,s)函数将用s替代$ 0中最左边最长的子串,该子串被( r)匹配。
s u b(s,p)返回字符串s在位置p后的后缀。s u b s t r(s,p,n)同上,并指定子串长度为n。
要在整个记录中替换一个字符串为另一个,使用正则表达式格式, /目标模式/,替换模式
/。例如改变学生序号4 8 4 2到4 8 9 9:
[root@localhost huangcd]# awk 'gsub(/4842/,4899) {print $0} END{print "nihao"}' grade.txt
J.Troll 07/99 4899 Brown-3 12 26 26
nihao
查询字符串s中t出现的第一位置。必须用双引号将字符串括起来。例如返回目标字符串
B u n n y中n y出现的第一位置,即字符个数。
[root@localhost huangcd]# awk 'BEGIN {print index("Bunny","ny")}' grade.txt
4
返回所需字符串长度,例如检验字符串J . Tr o l l返回名字及其长度,即人名构成的字符个数。
[root@localhost huangcd]# awk '$1=="J.Troll" {print length($1)" "$1}' grade.txt
7 J.Troll
还有一种方法,这里字符串加双引号。
[root@localhost huangcd]# awk 'BEGIN {print length("nihao ma")}'
8
m a t c h测试目标字符串是否包含查找字符的一部分。可以对查找部分使用正则表达式,返
回值为成功出现的字符排列数。如果未找到,返回0,第一个例子在A N C D中查找d。因其不
存在,所以返回0。第二个例子在A N C D中查找D。因其存在,所以返回A N C D中D出现的首位
置字符数。第三个例子在学生J . L u l u中查找u。
[root@localhost huangcd]# awk 'BEGIN {print length("nihao ma")}'
8
[root@localhost huangcd]# awk 'BEGIN {print match("ANCD",/d/)}'
0
[root@localhost huangcd]# awk 'BEGIN {print match("ANCD",/C/)}'
3
[root@localhost huangcd]# awk '$1=="J.Lulu" {print match($1,"u")}' grade.txt
4
使用s p l i t返回字符串数组元素个数。工作方式如下:如果有一字符串,包含一指定分隔
符- ,例如A D2 - K P 9 - J U 2 - L P - 1,将之划分成一个数组。使用s p l i t,指定分隔符及数组名。此
例中,命令格式为( " A D 2 - K P 9 - J U 2 - L P - 1 ",p a r t s a r r a y," - "),s p l i t然后返回数组下标数,这
里结果为4。
[root@localhost huangcd]# awk 'BEGIN {print split("123#456#789",myarr,"#");print myarr[1],myarr[2],myarr[3]}'
3
123 456 789
这里myarr用于存储得到的数组。
本章使用s u b发现并替换模式的第一次出现位置。字符串S T R包含‘poped popo pill’,执行下
列s u b命令s u b(/ o p /," o p ",S T R)。模式o p第一次出现时,进行替换操作,返回结果如下:
‘pO Ped pope pill’。文本文件中,学生J . Tr o l l的记录有两个值一样,“目前级别分”与“最高级别分”。只
改变第一个为2 9,第二个仍为2 6不动,操作命令为s u b(/ 2 6 /," 2 9 ",$ 0),只替换第一个出现
2 4的位置。注意J . Tr o l l记录需存在。
[root@localhost huangcd]# awk '$1=="J.Troll" sub(/26/,"29",$0)' grade.txt
s u b s t r是一个很有用的函数。它按照起始位置及长度返回字符串的一部分。例子如下:
[root@localhost huangcd]# awk '$1=="L.Tansley" {print substr($1,1,5)}' grade.txt
L.Tan
上面例子中,指定在域1的第一个字符开始,返回其前面5个字符。
如果给定长度值远大于字符串长度, a w k将从起始位置返回所有字符,要抽取L Ta n s l - e y
的姓,只需从第3个字符开始返回长度为7。可以输入长度9 9,a w k返回结果相同。
[root@localhost huangcd]# awk '$1=="L.Tansley" {print substr($1,3,99)}' grade.txt
Tansley
s u b s t r的另一种形式是返回字符串后缀或指定位置后面字符。这里需要给出指定字符串及
其返回字串的起始位置。例如,从文本文件中抽取姓氏,需操作域1,并从第三个字符开始:
[root@localhost huangcd]# awk '{print substr($1,3,99)}' grade.txt Tansley
Lulu
Bunny
Troll
Tansley
相关文章推荐
- linux shell编程指南第九章------AWK 介绍1
- linux shell编程指南第九章------AWK 介绍
- linux shell编程指南第九章------AWK 介绍3
- linux shell编程指南第七章------正则表达式介绍
- unix shell 编程指南第九章 awk
- linux shell编程指南第十章------sed 用法介绍
- linux shell编程指南第十章------sed 用法介绍2
- linux shell编程指南第十章------sed 用法介绍1
- (译)IOS block编程指南 1 介绍
- Linux Shell编程之介绍
- linux shell awk 流程控制语句(if,for,while,do)详细介绍
- 使XML编程更简单---JDOM介绍及编程指南
- linux shell awk 流程控制语句(if,for,while,do)详细介绍
- linux shell编程指南第四章------文件名置换
- Spark编程指南入门之Java篇六-RDD持久化介绍
- linux shell编程指南第十一章------------合并与分割2
- 树莓派Python编程指南--第九章(多媒体)
- 泛型介绍(C# 编程指南) 例子好,实现单链表
- linux shell编程指南第十八章------控制流结构
- PHPUnit袖珍指南 第九章 测试优先编程