AWK 学习分享

AWK 分享

          整理:SWFZZL

                Wenfei.si@gmail.com

http://www.gnu.org/home.html 官方网站

三个AWK 使用的例子 引入

1 通过 命令行  $ awk F “/t” ‘{print $0}’ test.txt

2 通过调用文本 $ awk –f scriptfile test.txt

3 直接使用 脚本文件的方式 $ scriptfile

AWK 详细介绍

1释义

1.1 英文原义:AhoWeinbergerKernighan

1.2 中文释义:三位创造者AhoWeinbergerKernighan统称

2简介

2.1 awk 是一种编程语言,用于在linux/unix下对文本和数据进行处理。

2.2 数据可以来自标准输入、一个或多个文件,或其它命令的输出。

2.3 awk的处理文本和数据的方式是这样的,它逐行扫描文件,从第一行到最后一行,寻找匹配的特定模式的行,并在这些行上进行你想要的操作。如果没有指定处理动作,则把匹配的行显示到标准输出 (屏幕),如果没有指定模式,则所有被操作所指定的行都被处理。

3规则和选项

3.1语法

awk [options] ‘script’ var=values file(s)

awk [options] –f scriptfile var=value file(s)

3.2 命令选项 (options)

-F fs or --field-separator fs

指定输入文件折分隔符,fs是一个字符串或者是一个正则表达式,如-F:

-v var=value or --asign var=value

赋值一个用户定义变量。

-f scripfile or --file scriptfile

从脚本文件中读取awk命令。

-mf nnn and -mr nnn

nnn值设置内在限制,-mf选项限制分配给nnn的最大块数目;-mr选项限制记录的最大数目。这两个功能是Bell实验室版awk的扩展功能,在标准awk中不适用。

 

3.3 模式和操作

awk脚本是由 模式和操作组成的:pattern {action} $ awk '/root/' test,或$ awk '$3 < 100' test。两者是可选的,如果没有模式,则action应用到全部记录,如果没有action,则输出匹配全部记录。默认情况下,每一个输入行都是一条记录,但用户可通过RS变量指定不同的分隔符进行分隔。

·         3.3.1 模式:指定一个行的范围该语法不能包括BEGINEND模式。

模式可以是以下任意一个:

·         /正则表达式/:使用通配符的扩展集。

·         关系表达式:可以用下面运算符表中的关系运算符进行操作,可以是字符串或数字的比较,如$2>%1选择第二个字段比第一个字段长的行。

模式匹配表达式:用运算符~(匹配)~!(不匹配)。用来在记录或者域内匹配正则表达式。如$ awk '$1 ~/^root/' test将显示test文件第一列中以root开头的行。

·         BEGIN:让用户指定在第一条输入记录被处理之前所发生的动作,通常可在这里设置全局变量。

·         END:让用户在最后一条输入记录被读取之后发生的动作。

3.3.2 操作

操作由一人或多个命令、函数、表达式组成,之间由换行符或分号隔开,并位于大括号内。主要有四部份:

·         变量或数组赋值

·         输出命令

·         内置函数

·         控制流命令

4常用系统环境变量介绍

变量

描述

$n

当前记录的第n个字段,字段间由FS分隔。

$0

完整的一条输入记录。

ARGC

命令行参数的数目。

ARGV

包含命令行参数的数组。

FIELDWIDTHS

字段宽度列表(用空格键分隔)

FILENAME

当前文件名。

FNR

NR,但相对于当前文件。

FS

字段分隔符(默认是任何空格)

IGNORECASE

如果为真,则进行忽略大小写的匹配。

NF

当前记录中的字段数。

NR

当前记录数。

OFMT

数字的输出格式(默认值是%.6g)

OFS

输出字段分隔符(默认值是一个空格)

ORS

输出记录分隔符(默认值是一个换行符)

RLENGTH

match函数所匹配的字符串的长度。

RS

记录分隔符(默认是一个换行符)

RSTART

match函数所匹配的字符串的第一个位置。

SUBSEP

数组下标分隔符(默认值是/034)

5运算符介绍

运算符与 C 语言功能基本一样

运算符

描述

= += -= *= /= %= ^= **=

赋值

?:

C条件表达式

||

逻辑或

&&

逻辑与

~ ~!

匹配正则表达式和不匹配正则表达式

< <= > >= != ==

关系运算符

空格

连接

+ -

加,减

* / &

乘,除与求余

+ - !

一元加,减和逻辑非

^ ***

求幂

++ --

增加或减少,作为前缀或后缀

$

字段引用

in

数组成员

 

6 AWK的记录 和 域

6.1 记录

每一个以换行符结束的行称为一个记录。

记录分隔符:默认的输入和输出的分隔符都是回车,保存在内建变量ORSRS中。

(Row Seperator)

$0变量:它指的是整条记录。如$ awk '{print $0}' test将输出test文件中的所有记录。

变量NR:一个计数器,每处理完一条记录,NR的值就增加1。如$ awk '{print NR,$0}' test将输出test文件中所有记录,并在记录前显示记录号。

Number of Row

6.2

记录中每个单词称做awk可跟踪域的个数并在内建变量NF中保存该值。

域分隔符:内建变量FS保存输入域分隔符的值,默认是空格或tab。我们可以通过-F命令行选项修改FS的值。如$ awk -F: '{print $1,$5}' test将打印以冒号为分隔符的第一,第五列的内容。可以同时使用多个域分隔符,这时应该把分隔符写成放到方括号中,如$awk –F '[:/t]' '{print $1,$3}' test,表示以空格、冒号和tab作为分隔符。输出域的分隔符默认是一个空格,保存在OFS中。如$ awk -F: '{print $1,$5}' test$1$5间的逗号就是OFS的值。(field sepreator

7 GAWK专用正则表达式通配符

符号

描述

/Y

匹配一个单词开头或者末尾的空字符串。

/B

匹配单词内的空字符串。

/<

匹配一个单词的开头的空字符串,锚定开始。

/>

匹配一个单词的末尾的空字符串,锚定末尾。

/w

匹配一个字母数字组成的单词

/W

匹配一个非字母数字组成的单词。

/‘

匹配字符串开头的一个空字符串。

/'

匹配字符串末尾的一个空字符串。

 

8案例 分析

·         $ awk '/^(no|so)/' test-----打印所有以模式noso开头的行。

·         $ awk '/^[ns]/{print $1}' test-----如果记录以ns开头,就打印这个记录。

·         $ awk '$1 ~/[0-9][0-9]$/(print $1}' test-----如果第一个域以两个数字结束就打印这个记录。

·         $ awk '$1 == 100 || $2 < 50' test-----如果第一个或等于100或者第二个域小于50,则打印该行。

·         $ awk '$1 != 10' test-----如果第一个域不等于10就打印该行。

·         $ awk '/test/{print $1 + 10}' test-----如果记录包含正则表达式test,则第一个域加10并打印出来。

·         $ awk '{print ($1 > 5 ? "ok "$1: "error"$1)}' test-----如果第一个域大于5则打印问号后面的表达式值,否则打印冒号后面的表达式值。

·         $ awk '/^root/,/^mysql/' test----打印以正则表达式root开头的记录到以正则表达式mysql开头的记录范围内的所有记录。如果找到一个新的正则表达式root开头的记录,则继续打印直到下一个以正则表达式mysql开头的记录为止,或到文件末尾。

9 AWK 编程

9.1变量

可以适用 系统变量和自定义变量 (自定义变量不可与系统变量同名)

9.2 Begin 模块

在对行记录扫描前开始执行

9.3 End   模块

在完成对所有行扫描后执行

9.4 重定向和管道

9.4.1重定向(redirect

字面理解是改变方向,在这里的意思是 对文本的输出方式进行修改

awk 可使用shell的重定向符进行重定向输出,如:$ awk '$1 = 100 {print $1 > "output_file" }' test。上式表示如果第一个域的值等于100,则把它输出到output_file中。也可以用>>来重定向输出,但不清空文件,只做追加操作。

9.4.2 管道
字面理解是 一种通道 ,在这里的意思是数据流向的方式,也可以理解成数据的载体

·         输出重定向需用到getline函数。getline从标准输入、管道或者当前正在处理的文件之外的其他输入文件获得输入。它负责从输入获得下一行的内容,并给NF,NRFNR等内建变量赋值。如果得到一条记录,getline函数返回1,如果到达文件的末尾就返回0,如果出现错误,例如打开文件失败,就返回-1。如:

$ awk 'BEGIN{ "date" | getline d; print d}' test。执行linuxdate命令,并通过管道输出给getline,然后再把输出赋值给自定义变量d,并打印它。

9.5 控制语句 (与C中一样,区别是不要加分号)

9.5.1 条件
1 if
2 else if
   3 嵌套 (条件语句)
9.5.2 循环
  • awk有三种循环:while循环;for循环;special for循环。
  • $ awk '{ i = 1; while ( i <= NF ) { print NF,$i; i++}}' test。变量的初始值为1,若i小于可等于NF(记录中域的个数),则执行打印语句,且i增加1。直到i的值大于NF.
  • $ awk '{for (i = 1; i<NF; i++) print NF,$i}' test。作用同上。
  • breadkcontinue语句。break用于在满足条件的情况下跳出循环;continue用于在满足条件的情况下忽略后面的语句,直接返回循环的顶端。如:

·         {for ( x=3; x<=NF; x++)

·                     if ($x<0){print "Bottomed out!"; break}}

·         {for ( x=3; x<=NF; x++)

·                     if ($x==0){print "Get next item"; continue}

·         }

  • next语句从输入文件中读取一行,然后从头开始执行awk脚本。如:

·         {

·         if ($1 ~/test/){next}

·          else {print}

·          }

  • exit语句用于结束awk程序,但不会略过END块。退出状态为0代表成功,非零值表示出错。
9.5.3 数组

awk中的数组的下标可以是数字和字母,称为关联数组。

下标与关联数组
  • 用变量作为数组下标。如:$ awk {name[x++]=$2};END{for(i=0;i<NR;i++) print i,name[i]}' test。数组name中的下标是一个自定义变量xawk初始化x的值为0,在每次使用后增加1。第二个域的值被赋给name数组的各个元素。在END 模块中,for循环被用于循环整个数组,从下标为0的元素开始,打印那些存储在数组中的值。因为下标是关健字,所以它不一定从0开始,可以从任何值开始。
  • special for循环用于读取关联数组中的元素。格式如下:

·         {for (item in arrayname){

·                  print arrayname[item]

·                  }

·         }

$ awk '/^tom/{name[NR]=$1}; END{for(i in name){print name[i]}}' test。打印有值的数组元素。打印的顺序是随机的。

  • 用字符串作为下标。如:count["test"]
  • 用域值作为数组的下标。一种新的for循环方式,for (index_value in array) statement。如:$ awk '{count[$1]++} END{for(name in count) print name,count[name]}' test。该语句将打印$1中字符串出现的次数。它首先以第一个域作数组count的下标,第一个域变化,索引就变化。
  • delete 函数用于删除数组元素。如:$ awk '{line[x++]=$1} END{for(x in line) delete(line[x])}' test。分配给数组line的是第一个域的值,所有记录处理完成后,special for循环将删除每一个元素。

9.6 函数

9.6.1 内置函数
数学函数

函数名称

返回值

atan2(x,y)

y,x范围内的余切

cos(x)

余弦函数

exp(x)

求幂

int(x)

取整

log(x)

自然对数

rand()

随机数

sin(x)

正弦

sqrt(x)

平方根

srand(x)

xrand()函数的种子

int(x)

取整,过程没有舍入

rand()

产生一个大于等于0而小于1的随机数

 

字符串函数(部分)

 

函数名

描述

gsub(r,s,t)

全局替换函数-在字符串t中用 s替换r,没有替换则给出t,否则 $0

index(s,t)

返回子串ts中的位置,没有则返回 0

match(s,r)

查看 r 是否在 s 中出现

sprintf("fmt",expr)

exprtprintf 格式进行输出

split(s,a,sep)

把子串加s加到a中,以sep 为分隔符

substr(s,p,n)

返回 s 字符串中 p 位置开始的n个字符

tolower(s)

把 字符串s中大写字母改成 小写

 

时间与日期函数

格式

描述

 

%a

星期几的缩写(Sun)

%A

星期几的完整写法(Sunday)

%b

月名的缩写(Oct)

%B

月名的完整写法(October)

%c

本地日期和时间

%d

十进制日期

%D

日期 08/20/99

%e

日期,如果只有一位会补上一个空格

%H

用十进制表示24小时格式的小时

%I

用十进制表示12小时格式的小时

%j

11日起一年中的第几天

%m

十进制表示的月份

%M

十进制表示的分钟

%p

12小时表示法(AM/PM)

%S

十进制表示的秒

%U

十进制表示的一年中的第几个星期(星期天作为一个星期的开始)

%w

十进制表示的星期几(星期天是0)

%W

十进制表示的一年中的第几个星期(星期一作为一个星期的开始)

%x

重新设置本地日期(08/20/99)

%X

重新设置本地时间(120000)

%y

两位数字表示的年(99)

%Y

当前月份

%Z

时区(PDT)

%%

百分号(%)

 

9.6.2 自定义函数 (使用时不需要定义)
Example
function insert(STRING, POS, INS) {
        before_tmp = substr(STRING, 1, POS)
        after_tmp = substr(STRING, POS + 1)
        return before_tmp INS after_tmp
}
{print insert($1,4,"aa")}
    
    

10底层抽屉

举个例子(家里的 衣柜,一般我们会把袜子,内衣什么的放在抽屉表层,因为要经常使用,而会把毛衣等一些使用频率不高的东西放在底层;)

这就是这章节需要阐述的内容:

10.1 The getline function
从数据流中读取

返回值 10-1 各自代表

1 读到一条记录

0 没有读到并已经到达文件末尾

-1 出现错误

# 例子 getline.awk -- test getline function
/^/.SH "?Name"?/ { 
        getline # get next line
        print $1 # print $1 of new line.
}

 

从文件中读取
while ( (getline < "data") > 0 )
        print

 

从管道中读取
"who am i" | getline me

 

10.2 The system() function

执行一个以表达方式给出的命令但是他不产生共程序处理的输出,它返回被执行命令的推出状态

BEGIN { if (system("mkdir dale") != 0) 
               print "Command Failed" }

 

$ awk -f system.awk
$ ls dale
$ awk -f system.awk
mkdir: dale: File exists
Command Failed

 

10.3 Directing output to files and pipes
文本重定向

print > "data.out"

print "a =", a, "b =", b, "max =", (a > b ? a : b) > "data.out"
管道重定向

print | command

{# words.awk - strip macros then get word count
sub(/^/.../,"")
print | "wc -w" 
}

 

(每次只能打开一定数量的管道,并用close来关闭管道)      

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值