awk学习笔记

awk程序由awk命令、括在引号(或写在文件)中的程序指令(可以有几个)以及输入文件的文件名组成,如果没有制定输入文件,输入则来自标准输入(stdin),即键盘。awk指令由模式操作,或模式与操作的组合组成。模式是bool语义,由多个括在两个正斜杠之间的regexp表达式或布尔表达式组成;操作由括在大括号内的一条或多条语句组成,语句间分号隔开。

在文件中的程序指令唯独少了引号,这部分指令为如下格式

  1. 模式 { 操作语句; 操作语句; 。。。;}
  2. 模式 {

    操作语句

    操作语句

    }

同sed一样,awk是一行一行的进行处理的,每一行的流程如下:

  1. awk使用一行(也叫记录,以换行符结束)作为输入,并将这一行赋给内部变量$0
  2. 行被空格分解成字段(单词),每一个字段存储在已编号的变量中,从$1开始(这一点和sed不同,后者是将一行看作一个字符流)
  3. 内部变量FS来确定字段的分隔符(流程2),默认是空格和\t,可以自己定义另外的分隔符。
  4. 根据模式的真假,确定是否进行操作,没有操作打印整行,没有模式,默认为真

简单输出使用print,eg:

awk '/Sally/{print "\t\tHave a nice day, " $1, $2 "!"}'

逗号,表示常量,变量间使用默认的OFS填充,引号中的就是常量$1这些就是变量

复杂输出(格式化输出,跟c的printf一致)使用printf,eg:

awk '{printf "The name is %-15s ID is %8d\n", $1, $3}' employees

一些内置变量:

NF: Number of Fields 当前行字段数目

NR: Number of Records    当前行号

awk –F'[ :\t]'说明使用空格,制表,冒号作为字段分隔符

所有的正则都可以用,甚至&都可以,而且默认使用的是扩展正则表达式,即便是{}都可以加上--re-interval来实现

关系运算符:<, >, <=, >=, ==, !=, ~, !=. eg:

$3 > 100{print $3} 或者 100 < $3{print $3}

但是~和!~就不要这样弄了

条件表达式

布尔表达式 ? 表达式1 : 表达式2

为真,该表达式值为表达式1,为假则反之,eg:

max = ($1 > $2) ? $1 : $2; print max

算术运算符:(按照浮点数来进行计算)

+, -, *, /, %, ^. eg:

$3 * $4 > 500

逻辑操作符:

&&, ||, !

复合模式

$3 > 100 || $4 ~ /Nice/

范围模式:匹配从第一个模式首次出现(为真)到第二个模式的首次出现(为真)之间的内容(如是循环),第二个没发现,显示到最后。eg:

/Tom/, /Susan/

赋值运算符:

=, +=, %=等等。eg:

$3 == "Chris" { $3 = "Christian"; print} #若$3为指定字符串,将之改为需求字符串并打印该行

变量不用声明自动初始化为0和空串,可以在数值和字符串间相互变化,变量名和C的要求相同:

=, +=, -=, *=, /=, %=, ^=, eg:

wage=$2*$3

递增,递减运算符:(性质和C相同)

++, --

命令行上用户自定义变量,eg:

awk –v month=11 –v year=2011 –f awkscropt filename

字段变量:$1, $2等等,可以修改,eg:

awk '{$5=1000*$3/$2; print}'

内置变量(linkhere)

BEGIN模式:在对输入文件进行任何处理前首先执行的操作

END模式:在对所有输入文件都进行处理过后执行的操作

输出重定向>:

awk 'print $1, $2 > "file"' filename

#将file(文件名)清空并打开(>的操作),将filename的1,2字段输出到file中

输入重定向getline:

awk 'BEGIN{"ls -l" | getline d; print d}' filename

#将ls –l输出的内容放到管道文件中,getline d完成将改管道的当前行放到d中的任务,注意这个d是可有可无的,有匿名变量保存getline的数据,并且print也会使用这个匿名变量的数据

管道|

awk的管道似乎和shell中的不同,它是在运行结束后再将管道用于后续的操作,eg:

print $1,$2 | "sort -n > testout"    #会在所有行都跑完过后才进行sort

管道也可以打开很多条,不知道书中的每次只能打开一个管道是什么意思

print $1,$2 | "sort -n > testout"

print $1,$2 | "sort -k2 > testout2"

可以使用close("sort -n")来关闭管道,我觉得关闭管道就是为了刷新输出,表示已经提供好输入,可以供管道右侧的命令使用了

system()函数,跟c中的同名函数的使用一样的,eg:

system("sort -n " ARGV[2]">tempfile")

system("mv tempfile "ARGV[2])

条件语句if,同C一样,多条语句才需要花括号框住

if(表达式){

语句; 语句; …

}

if/else语句:

{if(表达式){

语句; 语句; …

}

else{

语句; 语句; …

}

}

if/else if/…/else语句:

{if(表达式){

语句;…

}

else if(表达式){

语句;…

}

else if(表达式){

语句;…

}

else{

语句;…

}

}

while循环,do/while循环,for循环,continue,break:

{i=1; while(i<=NF){print NF, $i; ++i}}

{i=1; while(i<=NF){if($i<0){print "continue"; continue} print NF, $i; ++i;}} #注意在块语句后面可以不使用分号分隔,跟sed不同哟

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

if($x<0){print "break"; break}

}

next语句:停止本行操作,开始执行下一行的操作

exit语句:终止awk程序对文件的处理,不能跳过END,后跟awk返回值,eg:

exit (1)

数组(是个hashmap),使用时创建,使用[]索引:arrayname[key]

特殊for

{for(key in arrayname)){

print arrayname[key]

}

}

多维数组:matrix[key1, key2] = matrix[key1 SUBSEP key2],其中(SUBSEP = \034)

命令行处理参数

ARGV:从0开始,分别为awk命令,文件1……文件n

ARGC:ARGV的维数

由于awk会依次处理所有输入文件,因此可以在BEGIN中使用delete删除不需要的文件,eg:

BEGIN{print "ARGV[2]" is ARGV[2]}

{print}

字符串函数:

sub函数用于在目标串(默认为本记录)中查找能够匹配regex最长且最靠左的子串,然后用替换串取代找到的子串。

gsub函数替换能够匹配regex的所有的子串

index函数返回子串在字符串中第一次出现的位置,偏移量从1开始计算,格式:

index(字符串, 子串)

length函数返回字符串(默认为当前记录)中字符的个数,格式:

length(字符串)

length

substr函数返回从字符串制定位置(偏移量从1开始计算)开始,指定长度(默认为到末尾,如果超过末尾,也只输出到末尾)的一个子串,格式:

substr(字符串, 起始位置)

substr(字符串,起始位置,子串长度)

match函数返回regex在字符串中出现的位置,如果未出现,则返回0。match函数把内置变量RSTART设为子串在字符串中的起始位置,RLENGTH则设置为子串长度,可配合substr使用,格式:

match(字符串, 正则表达式)

split函数使用第三个参数(默认为FS)指定的字段分隔符,把字符串拆分成一个数组,格式:

split(字符串, 数组, 字段分隔符)

split(字符串, 数组)

sprintf函数,类似C的sprintf,格式化后赋给一个变量,格式:

variable=sprintf("含有格式说明的字符串", 表达式1, 表达式2, …, 表达式n)

内置算术函数

int函数:舍去小数点后所有数字,生成一个整数

rand函数:生成[0, 1)的浮点数

srand函数:srand(x)把x设成种子,不提供参数则根据当前系统时间

posted on 2011-11-16 16:27  Observer  阅读(2700)  评论(0编辑  收藏  举报

导航