`
ych4865
  • 浏览: 6842 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
最近访客 更多访客>>
社区版块
存档分类
最新评论

awk学习笔记

    博客分类:
  • awk
阅读更多
awk 学习笔记:
------------
·模式:
开始-主输入循环-结束

·主输入循环:模式匹配-记录-字段

·变量表达的字段:
[root@localhost ~]# echo a b c|awk 'BEGIN {one=1;two=2} {print $(one + two)}'
c

·-f选项:
[root@localhost ~]# awk -f list.awk name.log
andy,3233
steve,77899
[root@localhost ~]# cat list.awk
BEGIN { FS = " " }
{print $1 "," $2}
[root@localhost ~]# cat name.log
andy 3233
steve 77899

·分割符:
两个连续的分隔符间的字段值为空串。

·多个分隔符:(使用正则表达式表示)
[root@localhost ~]# awk -F "[:,]" '{print $1,$3}' name.log
andy xx
steve yy
[root@localhost ~]# cat name.log
andy,3233:xx
steve,77899:yy

·awk中对于变量赋值,空格为字符串间的连接操作符。

·模式匹配+算术运算:
使用awk,对于空行进行计数的脚本:
[root@localhost ~]# awk -f null_row.awk name.log
2
[root@localhost ~]# cat name.log
andy,3233:xx
steve,77899:yy


end,0:z
[root@localhost ~]# cat null_row.awk
/^$/ {
        ++x
}
END {
        print x
}

·算术运算:
求取平均值脚本:
[root@localhost ~]# awk -f avg_grade.awk grade.log
andy 79.75
lily 62.75
lucy 70
steve 75.75
ann 76
[root@localhost ~]# cat avg_grade.awk
{
total = $2 + $3 + $4 + $5
avg = total / 4
print $1,avg
}
[root@localhost ~]# cat grade.log
andy 86 78 99 56
lily 66 70 59 56
lucy 77 78 69 56
steve 82 78 87 56
ann 80 78 90 56

·系统变量
FS:输入字段分割符
OFS:输出字段分割符
RS:输入记录分隔符
ORS:输出记录分割符
NF:当前记录中字段的总数
NR:当前的记录数
FILENAME:当前输入处理的文件名

·横跨处理多行记录
[root@localhost ~]# awk -f multi_row.awk multi_row.log
andy steve 678-888
lucy lee 890-777
[root@localhost ~]# cat multi_row.log
andy steve
hangzhou
789 street
678-888

lucy lee
hangzhou
301 street
890-777
[root@localhost ~]# cat multi_row.awk
BEGIN {
        FS = "\n"
        RS = ""
}
{ print $1,$NF }

·关系操作符(主要用于模式匹配)
大于-等于-小于-匹配-不匹配:
等于的例子:
[root@localhost ~]# awk -F "[:,]" 'NF == 3 {print $1}' name.log
andy
steve
end
[root@localhost ~]# cat name.log
andy,3233:xx
steve,77899:yy


end,0:z

匹配的例子:
[root@localhost ~]# awk -F "[:,]" '$1 ~ /andy/ {print $1,$3}' name.log
andy xx

·逻辑(布尔)操作符
逻辑或-与-非
与的例子:
[root@localhost ~]# awk -F "[:,]" '$1 ~ /andy/ && $2 == 3233 {print $1,$2}' name.log
andy 3233

·格式化打印
print:打印字符串和字段,自动在句末加入回车;
printf:格式化输出,不会在句末自动加入回车,需要明确指定“\n”
[root@localhost ~]# awk '{printf "|%-10s|%3d\n",$1,$2}' grade.log
|andy      | 86
|lily      | 66
|lucy      | 77
|steve     | 82
|ann       | 80
[root@localhost ~]# cat grade.log
andy 86 78 99 56
lily 66 70 59 56
lucy 77 78 69 56
steve 82 78 87 56
ann 80 78 90 56

·向awk脚本传递参数(变量one、two)
[root@localhost ~]# awk -f var_input.awk one=1 two=2 grade.log
87 80
67 72
78 80
83 80
81 80
[root@localhost ~]# cat grade.log
andy 86 78 99 56
lily 66 70 59 56
lucy 77 78 69 56
steve 82 78 87 56
ann 80 78 90 56
[root@localhost ~]# cat var_input.awk
{
$2 += one
$3 += two
print $2,$3
}
另外一种获取方法:(使用-v选项,POSIX awk支持)
[root@localhost ~]# awk -v one=1 -v two=2 -f var_input.awk grade.log
87 80
67 72
78 80
83 80
81 80

#####进阶部分#####
·条件语句(基本上合C语言语法类似,下同)
一个例子:计算平均分,并显示为等级:
[root@localhost ~]# awk -f gtoclass.awk grade.log
andy      79.75    C
lily      62.75    D
lucy      70.00    C
steve     75.75    C
ann       76.00    C
[root@localhost ~]# cat grade.log
andy 86 78 99 56
lily 66 70 59 56
lucy 77 78 69 56
steve 82 78 87 56
ann 80 78 90 56
[root@localhost ~]# cat gtoclass.awk
{
total = $2 + $3 + $4 + $5
avg = total / ( NF -1 )
if (avg >= 90) class = "A"
else if (avg >= 80) class = "B"
else if (avg >= 70) class = "C"
else if (avg >= 60) class = "D"
else class = "E"
printf "%-10s%5.2f%5s\n",$1,avg,class
}

·循环语句
for while do-while
求平均值的另外一种方法:
[root@localhost ~]# awk -f for_avg.awk grade.log
andy 79.75
lily 62.75
lucy 70
steve 75.75
ann 76
[root@localhost ~]# cat grade.log
andy 86 78 99 56
lily 66 70 59 56
lucy 77 78 69 56
steve 82 78 87 56
ann 80 78 90 56
[root@localhost ~]# cat for_avg.awk
{
total = 0
for ( i =2; i <= NF; ++i )
        total += $i
avg = total / (NF - 1)
print $1,avg
}

使用while时的类似方法:
[root@localhost ~]# awk -f while_avg.awk grade.log
andy 79.75
lily 62.75
lucy 70
steve 75.75
ann 76
[root@localhost ~]# cat while_avg.awk
{
total = 0
i = 2
while ( i <= NF )
{
        total += $i
        i += 1
}
avg = total / (NF - 1)
print $1,avg
}

可以参考的一个综合的求阶乘的例子:
[root@localhost ~]# ./fact
enter number:5
the fact of 5 is 120
[root@localhost ~]# cat fact
awk '
BEGIN {
        printf "enter number:"
}

$1 ~ /^[0-9]+$/ {
        number = $1
        if ( number == 0 )
                fact = 1
        else
                fact = number
        for ( x = number - 1;x > 1;x-- )
                fact *= x
        printf "the fact of %d is %g \n",number,fact
        exit
}

{printf "invalid.enter number again:"}
' -

·影响程序流控制的语句
break:作用于循环语句,跳出循环
continue:作用于循环语句,跳出,进入下一个循环
next:作用于主输入循环,读取下一行输入行,返回到脚本顶部
exit:作用于主输入循环,退出主输入循环,将控制转移给END规则

·数组
选用NR作为数组下标的例子:
[root@localhost ~]# cat array_avg.awk
{
total = 0
for ( i =2; i <= NF; ++i )
        total += $i
avg[NR] = total / (NF - 1)
}

END {
for ( x = 1;x <= NR;x++ )
        class_avg_total += avg[x]
class_avg = class_avg_total / NR
for ( x = 1;x <=NR;x++ )
        if ( avg[x] >= class_avg )
                ++above_avg
        else
                ++below_avg
print "class avg:",class_avg
print "above avg:",above_avg
print "below avg:",below_avg
}
[root@localhost ~]# awk -f array_avg.awk grade.log
class avg: 72.85
above avg: 3
below avg: 2

·关联数组
数组的下标可以为字符串或数值
可以用于构造类似Python中的字典数据结构。
进行关联数组访问时,其输出数组条目顺序是随机的。
使用关联数组进行达到分数等级的个数的一个例子,综合以上各个内容:
[root@localhost ~]# awk -f fin_array_avg.awk grade.log
andy 79.75 C
lily 62.75 D
lucy 70 C
steve 75.75 C
ann 76 C
class avg: 72.85
above avg: 3
below avg: 2
C: 4
D: 1
[root@localhost ~]# cat fin_array_avg.awk
{
total = 0
for ( i =2; i <= NF; ++i )
        total += $i

avg_arr[NR] = total / (NF - 1)
avg = avg_arr[NR]

if (avg >= 90) class = "A"
else if (avg >= 80) class = "B"
else if (avg >= 70) class = "C"
else if (avg >= 60) class = "D"
else class = "E"
++class_arr[class]
print $1,avg,class
}

END {
for ( x = 1;x <= NR;x++ )
        class_avg_total += avg_arr[x]
class_avg = class_avg_total / NR

for ( x = 1;x <=NR;x++ )
        if ( avg_arr[x] >= class_avg )
                ++above_avg
        else
                ++below_avg
print "class avg:",class_avg
print "above avg:",above_avg
print "below avg:",below_avg

for ( class_x in class_arr )
        print class_x ":",class_arr[class_x] | "sort"
}

·split进行数组创建
[root@localhost ~]# echo 2 |awk -f split_month.awk
2 II
[root@localhost ~]# cat split_month.awk
BEGIN {
split("I,II,III,IV,V",numb,",")
}

$1 > 0 && $1 <= 5 {
print $1,numb[$1]
exit
}

{
        print "valid number."
        exit
}

·多维数组
模拟引用多维数组
简单的例子:
BEGIN {
for (i = 1;i <= 2; ++i)
for ( j = 1; j <=2; ++j)
bitmap[i,j] = "O"
}
...

·系统变量数组
ARGV:awk+附带的参数(-f参数除外)组成的数组,下标从0开始;
ARGC:参数数组个数。

·函数
算术函数:
三角函数-对数函数-平方根函数-随机函数-取整函数
举例如下:
[root@localhost ~]# awk -f int_func.awk
33.3333
33
[root@localhost ~]# cat int_func.awk
BEGIN {
print 100/3
print int(100/3)
exit
}

字符串函数:
gsub(r,s,t):在t中将r匹配到所有字符串,匹配为s ;(t未输入时,默认为$0)
sub(r,s,t):在t中将r首次匹配到字符串,匹配为s ;(t未输入时,默认为$0)

index(s,t):返回t在s中的位置;否则返回0;
match(s,r):返回正则表达式r在s中的起始位置;否则返回0;

substr(s,p,n):返回s中p位置之后的那个字符;(n未输入时,返回p之后剩余的字符)
split(s,a,sep):将s根据sep分割后写入数组a中,返回数组元素个数;

length(s):返回s的长度;(s未输入时,默认为$0)
sprintf(“fmt”,expr)对于expr使用fmt格式说明

tolower(s):大写转化为小写
toupper(s):小写转化为大写

一些例子:
index和substr综合:
将第一个单词的首字符变为大写:
[root@localhost ~]# echo abc |awk -f index_substr.awk
Abc
[root@localhost ~]# cat index_substr.awk
BEGIN {
upper="ABCDEFGH"
lower="abcdfegh"
}

{
firstchar=substr($1,1,1)
if (charplace = index(lower,firstchar))
        $1 = substr(upper,charplace,1)substr($1,2)
print $0
}

替换函数gsub和sub:
gsub的正则表达式替换,&为复制模式字符,\为转义符:(基本规则类似sed)
[root@localhost ~]# echo abc|awk '{gsub(/ab/,"\\start & end\\",$1);print $1}'
\start ab end\c

另外一个例子:
[root@localhost ~]# cat grade.log
andy 86 78 99 56
lily 66 70 59 56
lucy 77 78 69 56
steve 82 78 87 56
ann 80 78 90 56
[root@localhost ~]# cat sub_gsub.awk
awk '
{
gsub(/"/,"")
if (sub(/an/,"An")) print
if (sub(/li/,"Li")) print
}' $*
[root@localhost ~]# ./sub_gsub.awk grade.log
Andy 86 78 99 56
Lily 66 70 59 56
Ann 80 78 90 56

match函数:
函数两个系统变量:RSTART,RLENGTH;
RSTART:匹配子串的开始位置;此为返回值,不匹配时,返回为0
RLENGTH:匹配字符串的字符数。

如使用match进行正则表达式的字符大小匹配,不同awk版本的实现不一致;
遇到不区分大小写的情况,如下:
[root@localhost ~]# cat test.awk
/[a-z]/{
print $0
}
[root@localhost ~]# echo ABC|awk -f test.awk
ABC
[root@localhost ~]# echo abc|awk -f test.awk
abc
[root@localhost ~]# echo 123|awk -f test.awk
[root@localhost ~]#

自定义函数:
在脚本的模式规则定义之前声明;
在脚本内表达式可以使用的地方都可以调用自定义函数。
调取函数时,调取函数输入的参数,在被调函数内,使用其的“拷贝”值,不影响该参数调取函数的继续使用;
在被调函数内定义的变量,在调取函数中也可以使用;想要避免该情况,将该变量在被调函数声明时作为形参进行声明即可。
一个简单的例子:
[root@localhost ~]# echo 123 |awk -f fun-test.awk
call fun_test: with test parameter.
name: TEST
[root@localhost ~]# cat fun-test.awk
function fun_test(name)
{
print "name:",name
}

{
print "call fun_test: with test parameter."
fun_test("TEST")
}

·其他函数:
getline函数:
getline和next类似都是读取下一行,但是,有不同点:
next:读取下一行后,返回输入循环首语句;
getline:读取下一行,程序继续进行,不会返回循环首语句。
[root@localhost ~]# awk -f getline-test.awk grade.log
ann 80 78 90 56
[root@localhost ~]# cat getline-test.awk
/steve/{
getline
print $0
}
[root@localhost ~]# cat grade.log
andy 86 78 99 56
lily 66 70 59 56
lucy 77 78 69 56
steve 82 78 87 56
ann 80 78 90 56

使用getline读取文件和管道输入:
[root@localhost ~]# echo |awk -f getline-input.awk
andy 86 78 99 56
lily 66 70 59 56
lucy 77 78 69 56
steve 82 78 87 56
ann 80 78 90 56
root     :0           2012-12-03 22:05
[root@localhost ~]# cat getline-input.awk
{
while(getline < "grade.log" > 0)
print

"who"|getline me
print me
close("who")
}

system函数:
[root@localhost ~]# awk -f getfile.awk
please input file name:grade.log
andy 86 78 99 56
lily 66 70 59 56
lucy 77 78 69 56
steve 82 78 87 56
ann 80 78 90 56
cat end.
[root@localhost ~]# cat getfile.awk
BEGIN{
printf "please input file name:"
getline < "-"
file=$0
system("cat " file)
print "cat end."
}

print输出重定向到文件和管道:
一个简单的例子:
[root@localhost ~]# awk -f printfile.awk
please input file name:grade.log
grade.log
cat filename end.
file: grade.log word count:
10
[root@localhost ~]# cat printfile.awk
BEGIN{
printf "please input file name:"
getline < "-"
file=$0
print file >"filename"
system("cat filename")
print "cat filename end."
print "file:",file,"word count:"
print file |"wc -c"
}

参考资料:
sed & awk:Doughherty & Robbins.
分享到:
评论

相关推荐

    awk 学习笔记加例子

    **awk学习笔记与实例解析** awk 是一种强大的文本分析工具,尤其在Linux和Unix系统中广泛使用。它允许用户通过模式匹配和处理规则对输入数据进行操作,特别适合于处理结构化的文本文件,如日志文件、配置文件等。本...

    PDF电子书《Awk学习笔记2010修改版》

    ### PDF电子书《Awk学习笔记2010修改版》相关知识点 #### AWK简介 AWK是一种强大的脚本语言,由Alfred V. Aho、Peter J. Weinberger和Brian W. Kernighan在1977年设计并实现。这三位计算机科学家的名字首字母合成了...

    awk学习笔记(简单易学)

    ### awk学习笔记精要 #### 1. awk简介 awk是一种功能强大的文本处理语言,主要用于在Linux/Unix环境中处理文本和数据。它能够从标准输入、文件或其它命令的输出中提取并处理数据,支持自定义函数和动态正则表达式...

    linux awk学习笔记

    `awk`的学习需要结合实际案例进行,通过编写和运行脚本来熟悉其用法和功能。 总结,`awk`是Linux文本处理的重要工具,其灵活性和强大的功能使其在数据分析、日志分析等领域有着广泛的应用。通过深入学习和实践,...

    awk 学习笔记

    ### awk 学习笔记 #### 1. awk简介 awk是一种功能强大的文本处理语言,主要用于Linux和Unix环境下的数据处理。它可以处理来自标准输入、文件或命令输出的数据,支持自定义函数和动态正则表达式等功能,使其成为...

    awk学习笔记,从论坛整理而来

    `awk` 是一种强大的文本分析工具,常用于处理和解析结构化的文本文件,如日志文件、配置文件等。在Linux和Unix系统中,`awk` ...通过不断地实践和学习,你将能够有效地利用 `awk` 解决日常工作中遇到的文本处理问题。

    linux下AWK学习笔记

    本笔记将详细介绍AWK的基本概念、语法、命令选项以及常用的特性。 ### 1. AWK简介 AWK是由三位开发者的首字母命名的——Alfred V. Aho、Peter J. Weinberger和Brian W. Kernighan。它是一种内置了多种功能的语言,...

    AWK学习笔记.doc

    本笔记主要涵盖了AWK的基础知识和高级特性,旨在帮助读者理解和掌握这一实用工具。 **一.1 什么是AWK?** AWK是由Aho、Weinberger和Kernighan三位计算机科学家开发的,它的名字就是由他们的姓氏首字母组成的。AWK是...

    awk学习笔记(学习awk编程的好帮手)

    awk是一种强大的文本分析工具,广泛应用于Linux和Unix系统中。...学习awk能够极大地提升在Linux和Unix环境下处理文本数据的能力。通过深入理解和实践,你可以利用awk解决各种数据处理挑战,提高工作效率。

    awk学习笔记.pdf

    AWK是一种编程语言,用于在Linux环境下对文本和数据进行处理和分析。它是许多UNIX系统中的标准工具,并且是文本处理的强大工具。AWK通过模式匹配来处理文本文件,其中可以指定一系列规则,称为模式和动作,来对输入...

    Awk学习笔记和指南

    awk 是一种编程语言,用于在linux/unix下对文本和数据进行处理。数据可以来自标准输入、一个或多个文件,或其它命令的输出。它支持用户自定义函数和 动态正则表达式等先进功能,是linux/unix下的一个强大编程工具。...

    sed与awk(第二版)学习笔记

    sed与awk(第二版)学习笔记

    Awk学习笔记

    1. awk简介 2. awk命令格式和选项 2.1. awk的语法有两种形式 2.2. 命令选项 3. 模式和操作 3.1. 模式 3.2. 操作 4. awk的环境变量 5. awk运算符 6. 记录和域 6.1. 记录 6.2. 域 6.3. 域分隔符 7. gawk专用...

    sed awk学习

    sed awk 学习笔记 SED 是一个“非交互式”的面向字符流的编辑器,它可以在一个地方指定所有的编辑指令,然后通过文件传递一次来执行他们。但是它在每次多于一行的处理能力方面有限制。SED 的优点是可以批量处理文件...

    awk学习的相关内容

    文件名`awk学习-20101008.doc`可能包含了作者在2010年10月8日整理的awk学习笔记,涵盖了基本语法、常用命令和实战案例。可能包括以下内容: 1. **基本语法**:介绍awk的基本结构,如模式-动作对,以及如何指定输入...

Global site tag (gtag.js) - Google Analytics