`

AWK编程总结(2)

阅读更多

1.6 awk关系、布尔运算符、表达式

AWK的大部分运算符及其意义与C/C++JavaLinux等相似,如:

< 小于

> 大于

<= 小于等于

>= 大于等于

== 等于

!= 不等于

|| 逻辑或

&& 逻辑与

! 逻辑非

+

-

*

/

%

^** 乘方

++x 在返回x值之前,x变量加1

x++ 在返回x值之后,x变量加1

 

AWK独有的运算符有:~ 匹配正则表达式、!~ 不匹配正则表达式。

 

awk 'BEGIN {FS=":"} $1~/root/' /etc/passwd ~正则表达式为匹配字符串

awk 'BEGIN {FS=":"} {if($3==10||$4==10) print $0}' /etc/passwd ==是为数字匹配

awk 'BEGIN {FS=":"} {if($3~10||$4~10) print $0}' /etc/passwd  正则表达式~表示包含

 

awk执行文件:

#!/bin/awk -f

BEGIN {FS=","}

{ total=$4+$5+$6+$7+$8

avg=total/5

print $1,avg

}

 

与其他编程语言一样,awk表达式用于存储、操作和获取数据,一个awk表达式可由数值、字符常量、变量、操作符、函数和正则表达式自由组合而成。

变量是一个值的标识符,定义awk变量非常方便,只需定义一个变量名并将值赋给它即可。变量名只能包含字母、数字和下划线,而且不能以数字开头,这与C/C++Java的变量定义规范相同。

 

1.7 awk格式化输出:

awk的一大主要功能是产生报表,报表就要求按照预定的格式输出,awk借鉴C语言的语法,定义了printf输出语句,它可以规定输出的格式。

printfprintf (格式控制符,参数)

awk格式控制符及其意义如下:

- 左对齐

width 域的步长

.prec 小数点右边的位数

%c ASCII字符

%d 整型数

%e 浮点数,科学记数法

%f 浮点数

%o 八进制数

%s 字符串

%x 十六进制数

 

awk 'BEGIN {FS=","; print "NAME\t\tPHCHNUMBER"} {printf("%-15s\t%s\n",$1,$3)}' sturecord2

结果为:

NAME            PHCHNUMBER

Li Hao          80283058

Zhang Ju        2343255

Wang Bin        2342353

Zhu Lin         23434

 

1.8 awk内置字符串函数

awk内置字符串函数极为强大,是Shell处理字符串的常用工具。常用的字符串函数如下:

 sub(regular expression,substitution string);
sub(regular expression,substitution string,target string);

gsub(r,s) 在输入文件中用s替换r

gsub(r,s,t) t中用s替换r

index(s,t) 返回s中字符串第一个t的位置

length(s) 返回s的长度

match(s,t) 测试s是否包含匹配t的字符串

split(r,s,t) t上将r分成序列s

sub(r,s,t) t中第1次出现的r替换为s

substr(r,s) 返回字符串r中从s开始的后缀部分

substr(r,s,t) 返回字符串r中从s开始长度为t的后缀部分

toupper(string)tolower(string)以上两个函数分别返回参数字符串的大写和小写的形式。

variable = sprintf("string with format specifiers ",expr1,expr2,...)
该函数和printf的差别等同于C语言中printfsprintf的差别。前者将格式化后的结果输出到输出流,而后者输出到函数的返回值中。

systime()该函数返回当前时间距离197011日之间相差的秒数。

strftime()时间格式化函数,其格式化规则等同于C语言中的strftime函数提供的规则:

数据格式含义

%a Abbreviated weekday name

%A Full weekday name

%b Abbreviated month name

%B Full month name

%c Date and time representation appropriate for locale

%d Day of month as decimal number (01 – 31)

%H Hour in 24-hour format (00 – 23)

%I Hour in 12-hour format (01 – 12)

%j Day of year as decimal number (001 – 366)

%m Month as decimal number (01 – 12)

%M Minute as decimal number (00 – 59)

%p Current locale's A.M./P.M. indicator for 12-hour clock

%S Second as decimal number (00 – 59)

%U Week of year as decimal number, with Sunday as first day of week (00 – 53)

%w Weekday as decimal number (0 – 6; Sunday is 0)

%W Week of year as decimal number, with Monday as first day of week (00 – 53)

%x Date representation for current locale

%X Time representation for current locale

%y Year without century, as decimal number (00 – 99)

%Y Year with century, as decimal number

 

/> awk 'BEGIN{ print strftime("%D",systime())}'

    11/15/11

/> awk 'BEGIN{ now = strftime("%T"); print now}'

    23:17:29

 

常用的内置数学函数如下:

atan2(x,y) y,x范围内的余切

cos(x) 余弦函数

exp(x) 求幂

int(x) 取整

log(x) 自然对数

sin(x) 正弦函数

sqrt(x) 平方根

 

  /> awk 'BEGIN{print 31/3}'

    10.3333

  /> awk 'BEGIN{print int(31/3)}'

    10

 

    AWK还支持用户自定义函数。用户自定义函数可以放在awk脚本的任何可以放置模板和动作的地方。

方法如下:

    function methodName(parameter1,parameter2,...) {

        //statements

        //return expression

    }

给函数中本地变量传递值只使用变量的拷贝。数组通过地址或者指针传递,所以可以在函数内部直接改变数组元素的值。

函数内部使用的任何没有作为参数传递的变量都被看做是全局变量,也就是这些变量对于整个程序都是可见的。如果变量在函数中发生了变化,那么就是在整个程序中发生了改变。

唯一向函数提供本地变量的办法就是把他们放在参数列表中,这些参数通常被放在列表的最后。如果函数调用没有提供正式的参数,那么参数就初始化为空。return语句通常就返回程序控制并向调用者返回一个值。

  /> cat grades

    20 10

    30 20

    40 30

 

   /> cat add.sc

    function add(first,second) {

            return first + second

    }

    { print add($1,$2) }

 

   /> awk -f add.sc grades

    30

    50

    70

 

1.9 awk条件语句和循环语句

awk条件语句和循环语句与C语言的语法完全一样.

if (条件表达式)

    动作1

[else

    动作2]

 

while (条件表达式)

     动作

 

 

do

    动作

while (条件表达式)

 

for (设置计数器初值;测试计数器;计数器变化)

   动作

 

awk中还提供了一种special for的循环,见如下声明:

    for (item in arrayname) {

        print arrayname[item]

    }

 

1.10 awk数组

数组是用于存储一系列值的变量,这些值之间通常是有联系的,可通过索引来访问数组的值,索引需要用中括号括起,数组的基本格式为:

array[index]=value

关联数组是指数组的索引可以是字符串,也可以是数字。关联数组在索引和数组元素值之间建立起关联,对每一个数组元素,awk自动维护了一对值:索引和数组元素值。关联数组的值无需以连续的地址进行存储,awk的所有数组都是关联数组。

字符串和数字之间的差别是明显的,如,我们使用array[09]指定一个数组值,如果换成array[9]就不能指定到与array[09]相同的值。

 

由于awk中数组的下标可以是数字和字母,数组的下标通常被称为关键字(key)。值和关键字都存储在内部的一张针对key/value应用hash的表格里。由于hash不是顺序存储。

数组和变量一样,都是在使用时自动创建的,awk也同样会自动判断其存储的是数字还是字符串。一般而言,awk中的数组用来从记录中收集信息,可以用于计算总和、统计单词以及跟踪模板被匹配的次数等等。

    /> cat employees

    Tom Jones       4424    5/12/66         543354

    Mary Adams      5346    11/4/63         28765

    Sally Chang     1654    7/22/54         650000

    Billy Black     1683    9/23/44         336500

 

    /> awk '{name[x++] = $2}; END{for (i = 0; i < NR; i++) print i, name[i]}' employees   

    0 Jones

    1 Adams

    2 Chang

    3 Black

    在上例中,数组name的下标是变量xawk初始化该变量的值为0,在每次使用后自增1,读取文件中的第二个域的值被依次赋值给name数组的各个元素。在END模块中,for循环遍历数组的值。因为下标是关键字,所以它不一定从0开始,可以从任何值开始。

 

    #这里是用内置变量NR作为数组的下标了。

    /> awk '{id[NR] = $3}; END {for (x = 1; x <= NR; x++) print id[x]}' employees

    4424

    5346

    1654

    1683

 

   再如: /> cat db

    Tom Jones

    Mary Adams

    Sally Chang

    Billy Black

    Tom Savage

    Tom Chung

    Reggie Steel

    Tommy Tucker

 

    /> awk '/^Tom/{name[NR]=$1}; END {for(i = 1;i <= NR; i++) print name[i]}' db

    Tom

 

 

 

    Tom

    Tom

 

    Tommy

    从输出结果可以看出,只有匹配正则表达式的记录的第一个域被赋值给数组name的指定下标元素。因为用NR作为下标,所以数组的下标不可能是连续的,因此在END模块中用传统的for循环打印时,不存在的元素就打印空字符串了。下面我们看看用special for的方式会有什么样的输出。

    /> awk '/^Tom/{name[NR]=$1};END{for(i in name) print name[i]}' db

    Tom

    Tom

    Tommy

    Tom

 

    下面我们看一下用字符串作为下标的例子:(如果下标是字符串文字常量,则需要用双引号括起来)   

    /> cat testfile2

    tom

    mary

    sean

    tom

    mary

    mary

    bob

    mary

    alex

    /> awk '/tom/{count["tom"]++}; /mary/{count["mary"]++}; END{print "There are " count["tom"] \

        " Toms and " count["mary"] " Marys in the file."} testfile2

    There are 2 Toms and 4 Marys in the file.

    在上例中,count数组有两个元素,下标分别为tommary,每一个元素的初始值都是0,没有tom被匹配的时候,count["tom"]就会加一,count["mary"]在匹配mary的时候也同样如此。END模块中打印出存储在数组中的各个元素。

 

    /> awk '{count[$1]++}; END{for(name in count) printf "%-5s%d\n",name, count[name]}' testfile2

    mary 4

    tom  2

    alex 1

    bob  1

    sean 1

    在上例中,awk是以记录的域作为数组count的下标。

 

    /> awk '{count[$1]++; if (count[$1] > 1) name[$1]++}; END{print "The duplicates were "; for(i in name) print i}' testfile2

    The duplicates were

    mary

    tom

    在上例中,如count[$1]的元素值大于1的时候,也就是当名字出现多次的时候,一个新的数组name将被初始化,最后打印出那么数组中重复出现的名字下标。

 

    之前我们介绍的都是如何给数组添加新的元素,并赋予初值,现在我们需要介绍一下如何删除数组中已经存在的元素。要完成这一功能我们需要使用内置函数delete,见如下命令:

    /> awk '{count[$1]++}; \

        END{for(name in count) {\

                if (count[name] == 1)\

                    delete count[name];\

            } \

            for (name in count) \

                print name}' testfile2

    mary

    tom

    上例中的主要技巧来自END模块,先是变量count数组,如果数组中某个元素的值等于1,则删除该元素,这样等同于删除只出现一次的名字。最后用special for循环打印出数组中仍然存在的元素下标名称。

 

    最后我们来看一下如何使用命令行参数数组,见如下命令:

    /> awk 'BEGIN {for(i = 0; i < ARGC; i++) printf("argv[%d] is %s.\n",i,ARGV[i]); printf("The number of arguments, ARGC=%d\n",ARGC)}' testfile "Peter Pan" 12

    argv[0] is awk.

    argv[1] is testfile.

    argv[2] is Peter Pan.

    argv[3] is 12.

    The number of arguments, ARGC=4

    从输出结果可以看出,命令行参数数组ARGV是以0作为起始下标的,命令行的第一个参数为命令本身(awk),这个使用方式和C语句main函数完全一致。

 

    /> awk 'BEGIN{name=ARGV[2]; print "ARGV[2] is " ARGV[2]}; $1 ~ name{print $0}' testfile2 "bob"   

    ARGV[2] is bob

    bob

    awk: (FILENAME=testfile2 FNR=9) fatal: cannot open file `bob' for reading (No such file or directory)

    先解释一下以上命令的含义,name变量被赋值为命令行的第三个参数,即bob,之后再在输入文件中找到匹配该变量值的记录,并打印出该记录。

    在输出的第二行报出了awk的处理错误信息,这主要是因为awkbob视为输入文件来处理了,然而事实上这个文件并不存在,下面我们需要做进一步的处理来修正这个问题。

    /> awk 'BEGIN{name=ARGV[2]; print "ARGV[2] is " ARGV[2]; delete ARGV[2]}; $1 ~ name{print $0}' testfile2 "bob"   

    ARGV[2] is bob

    bob

    从输出结果中我们可以看到我们得到了我们想要的结果。需要注意的是delete函数的调用必要要在BEGIN模块中完成,因为这时awk还没有开始读取命令行参数中指定的文件。

 

分享到:
评论

相关推荐

    sed命令和awk编程教程

    ### sed命令和awk编程教程知识点概述 #### 一、sed命令基本概念与使用方法 - **sed命令简介**: - `sed` 是一个非交互式的流编辑器(Stream Editor),主要用于自动化文本处理任务,尤其适合处理大型文件或者复杂的...

    Effective.Awk.Programming.3rd.Edition

    描述:“高效awk编程,高清文字版” 这里的描述向我们传达了这本书的目的和特色。首先,“高效”强调了效率和优化,意味着书中将教你如何编写出高效能的awk脚本。其次,“高清文字版”可能意味着这本书的电子版格式...

    The AWK Programming Language 中文版

    AWK是一种非常实用的编程语言,它在文本处理和数据分析方面表现出色。它的特点是编写程序非常简单,即便是只有一两行的程序也能完成复杂的任务。AWK非常适合那些需要快速解决特定数据处理问题的场景。 ### AWK程序...

    关于awk的用法总结

    在shell编程中,awk的灵活性和强大功能使其成为不可或缺的一部分。 1. **基本语法** awk的工作原理基于模式匹配和执行相应的动作。基本语法结构是 `awk 'pattern {action}' file`。pattern是匹配条件,action是...

    awk实例入门教程.pdf

    2. **变量`$0`与`FS`**:在awk中,`$0`总是指代当前行,而`FS`是字段分隔符,决定数据是如何被切分的。默认情况下,`FS`为空白字符,但在处理复杂的数据格式时,如`/etc/passwd`文件中使用冒号(:)分隔,可以通过设置...

    awk语言编程使用规则

    总结来说,awk 是一种强大的文本处理工具,通过模式匹配和自定义操作,可以高效地处理和解析文本数据。熟练掌握 awk,能帮助我们在处理大量文本信息时提高效率,尤其在系统管理和数据分析领域有着广泛的应用。

    grep,sed, awk 总结

    在处理文本时,awk允许自定义字段变量,以实现对字段的引用和操作,如`$1`、`$2`分别代表第一、第二字段。 ### sed sed(stream editor)是一个流编辑器,用于对文本进行过滤和转换。sed一次处理一行,可以执行...

    awk.Effective.awk.Programming.Universal.Text.Processing.and.Pattern.Matching.4th

    《Effective awk Programming: Universal Text Processing and Pattern Matching》(第4版)是一本由Arnold Robbins编写的关于awk编程语言的专业指南。这本书不仅深入探讨了awk编程的核心概念,还提供了大量的实际...

    awk知识文档学习

    根据您提供的文件内容,这里总结了关于awk的一些知识点。 ### 1. Awk概述 Awk是一种编程语言,用于处理文本模式和报告生成。它主要用于Linux操作系统,并广泛应用于UNIX Shell编程中。Awk按照记录和字段的方式来...

    linux shell 编程之 awk用法

    ### Linux Shell 编程之 Awk 用法详解 在Linux环境下,Awk是一种强大的文本处理工具,用于处理结构化的数据。Awk不仅能够执行基本的打印操作,还能进行复杂的模式匹配、数据筛选和数学运算,是Linux系统管理员和...

    The AWK Programming Language 1988年 pdf

    ### AWK编程语言知识点概述 #### 一、AWK编程语言简介 - **起源与开发者**:AWK编程语言最初由Alfred Aho、Brian Kernighan和Peter Weinberger于1977年开发。 - **特点**:AWK是一种模式匹配语言,用于编写...

    linux环境下awk开发

    2. **简单易用**:相较于C语言等编程语言,AWK的语法更为简洁,使得开发过程更加高效。AWK提供了从简单的命令行工具到复杂的程序设计语言的解决方案,用户可以根据问题的复杂程度选择合适的工具。 3. **易于获取**...

    linux awk学习笔记

    Linux中的`awk`是一个强大的文本分析工具...总结,`awk`是Linux文本处理的重要工具,其灵活性和强大的功能使其在数据分析、日志分析等领域有着广泛的应用。通过深入学习和实践,我们可以充分利用`awk`来提高工作效率。

Global site tag (gtag.js) - Google Analytics