awk 学习笔记 -- by wdx
时间:2007-10-17 来源:rha030
现在有这样一个表coins.txt,它的每一列的内容分别是 metal、weight in ounces、 date minted、country of origin和description,内容如下:
gold 1 1986 USA American Eagle |
如果想查看所有金币的信息,可以
awk '/gold/' coins.txt |
如果想查看金币的日期和国家,可以:
awk '/gold/{print $3 " " $4}' coins.txt |
如果想查看1980以前的货币,可以:
awk '{if ($3 < 1980) print}' coins.txt |
如果想统计有多少种货币,可以:
awk 'END {print NR,"coins"}' coins.txt |
如果想统计所有金币的价值,可以:
awk '/gold/ {ounces += $2} END {print "value = $" 425*ounces}' coins.txt |
即把所有金币的重量加到一起,再乘以单位金的价格就得到总的价值。
二、awk的命令行:
awk -Fch 'spcecial_lines{cmd1;cm2...}' processed_txt |
这里:
- -F指定域(列)之间的分隔符为ch,awk默认的分隔符是空格或者TAB,但有些文件的分隔符可能是":"等,比如/etc/passwd文件
- spcecial_lines指定文本中需要处理的行,如果没有指定表示对文本中的所有行运行后面的cmd,指定的方法有多种spcecial_lines,后面会具体说明。
- 如果没有指定命令,默认执行print,即打印当前行,每个命令以;隔开
- 如果没有指定被处理文件,则默认从标准输入读取,直到ctrl+D结束,另外可以指定多被处理文件,awk会把多个文件产生的输出连在一起。
awk 'cmd' var1=value1 processed_txt |
需要注意的是如果awk的命令是在命令中指定,需要加上''避免shell解释。
三、 awk的语法
1.spcecial_lines的指定,awk中可以通过多种方式来指定需要处理的行
- 使用正则表达式处理那些含有和模式匹配的文本的行,比如上面的“/gold/”就可以看作是一种简单的正则表达式,至于其他的正则表达式不再深入,和一般的正则表达式的语法相同
- 处理某一个域是符合某种模式的,比如
awk '$1~/^gold/{print $2}' coin.txt |
- 通过行号指定:NR==10,这里可以使用<,<=.,==,!=,>=,>等关系符得到相应的行的范围,另外NF==0,表示所有空行,NF是当前行的域的个数
- 指定连结的行,可以用/^foo/,/^bar/或者NR==10,NR==20来确定一个范围
- 指定行的条件可以用逻辑关系符连接,比如
((NR>=30)&&($1=="France")) || ($1 == "Norway") |
- 比较特殊的是前面看到的BEGIN和END,这两个标志分别指定awk在处理所有行之前和之后执行相应的命令,BEGIN多用于变量的初始化,而END而用于统计一些信息。
awk是一种弱类型的编程语言,它在使用变量时不需要先声明。awk中根据变量值的不同,数字和字符操作可以分为以下几种情况:
- 数字串,符合以下数字形式的,不管是否加“”:
789 3.141592654 +67 +4.6E3 -34 -2.1e-2 |
awk '{print $2+1}' test |
awk '{print substr($2,1,4)}' test |
awk 'BEGIN{var="1234";print var+1}' test |
- 加“”的除了数字以外的字符串,比如"foo",这种变量只能参与字符串操作,如果放在数字操作里它的值为0,比如:
awk 'BEGIN{var="foo";print var+1}' test |
((( $1 + 0 ) == $1 ) && ( $1 > 100 )) |
- 不加""的除了数字以外的字符串,变量的值会被认为是0,打印这个变量输出是空行
awk 'BEGIN{var=foo;if(var==0) printf("yes\n");print var}' test |
- 另外,awk提供了一些已经定义好的变量:
NF: 当前行的域的个数,最后一个域用$NF
FILENAME: 被处理的文件名
FS: ”field separator“,域分隔符,默认是空格和TAB
RS: "record separator" 记录的分隔符,默认是换行
OFS: 输出文本中的域分隔符,默认是空格
ORS:输出文本中的记录分隔符,默认是换行
OFMT:浮点数的输出格式,默认是"%.6g"
3. awk的数组
awk的数组不需要声明,也不需要指定大小,并且索引是从1开始的,另外索引不一定是数字,也可以是字符串,即一种关联数组。使用格式如下:
some_array[1], some_array[2], some_array[3] |
使用数组的一个例子,把/etc/passwd文件中的第2列,换成/etc/shadow的第2列
awk 'BEGIN{OFS=FS=":"} NR==FNR{a[$1]=$2}NR>FNR{$2=a[$1];print}' shadow passwd |
这里的FNR是针对每个文件计数的,而NR从第一个文件的第一个记录开始直到最后一个文件的最后一条记录统一计数,这样NR>NNR限定的就是第2个文件了,上面这个命令就是先把/etc/shadow的第2列保存到数组a中,然后把/etc/passwd的第2列换成数组中的值,数组a的索引是$1,即使这两个文件中记录的顺序不同也可以直接实现需求。
4.awk的数值运算和字符串操作
awk的数值操作基本和C语言相同:
Arithmetic operations:
+ Addition.Shorthand assignments:
- Subtraction.
* Multiplication.
/ Division.
% Mod.
++ Increment.
-- Decrement.
x += 2 -- is the same as: x = x + 2
x -= 2 -- is the same as: x = x - 2
x *= 2 -- is the same as: x = x * 2
x /= 2 -- is the same as: x = x / 2
x %= 2 -- is the same as: x = x % 2
另外还有几个用于数值操作的函数:
sqrt() Square root.
log() Base \Ie\i log.
exp() Power of \Ie\i.
int() Integer part of argument.
字符操作的函数有:
-
length()
Length of string.
-
substr(<string>,<start of substring>,<max length of substring>)
Get substring.
-
split(<string>,<array>,[<field separator>])
Split string into array, with initial array index being 1.
-
index(<target string>,<search string>)
Find index of search string in target string.
-
sprintf()
Perform formatted print into string.
awk作为一种编程语言,提供了程序流的控制结构和C语言十分相似:
Scanning through an associative array with "for":
if (<condition>) <action 1> [else <action 2>]
while (<condition>) <action>
for (<initial action>;<condition>;<end-of-loop action>) <action>
for (<variable> in <array>) <action>Unconditional control statements:
break Break out of "while" or "for" loop.6.awk的输出格式
continue Perform next iteration of "while" or "for" loop.
next Get and scan next line of input.
exit Finish reading input and perform END statements.
printf可以用于格式化输出,使用格式:
%[<number>]<format code>
其中的number:
前面的-指定左对齐,否则是右对齐
整数部分对于输出字符串指定的输出最少所占宽度,如果输出内容长度超过这个值会超出这个宽度
小数部分对于浮点数指定小数部分的位数,对于字符串指定最多占的宽度
前面的0表明剩余空间用0补全
|
参考:http://www.vectorsite.net/tsawk.html
http://www.chinaunix.net/jh/24/577044.html
另外一个不错的参考:http://www.chinaitpower.com/A/2003-02-14/50128.html