awk

来源:互联网 发布:java 类 继承 编辑:程序博客网 时间:2024/04/25 04:53
awk 是一种编程语言,用于在linux/unix下对文本和数据进行处理。数据可以来自标准输入、一个或多个文件,或其它命令的输出。它支持用户自定义函数和动态正则表达式等先进功能,是linux/unix下的一个强大编程工具。它在命令行中使用,但更多是作为脚本来使用。awk的处理文本和数据的方式是这样的,它逐行扫描文件,从第一行到最后一行,寻找匹配的特定模式的行,并在这些行上进行你想要的操作。如果没有指定处理动作,则把匹配的行显示到标准输出 (屏幕),如果没有指定模式,则所有被操作所指定的行都被处理。awk分别代表其作者姓氏的第一个字母。因为它的作者是三个人,分别是Alfred Aho、Brian Kernighan、Peter Weinberger。gawk是awk的GNU版本,它提供了Bell实验室和GNU的一些扩展。下面介绍的awk是以GUN的gawk为例的,在 linux系统中已把awk链接到gawk,所以下面全部以awk进行介绍。  

awk
调用:
1.调用awk:

第一种方式:命令行方式
awk [-F field-separator] 'commands' input-file(s)
[-F域分隔符]是可选的,因为awk使用空格作为缺省的域分隔符,因此如果要浏览域间有空格的文本,不必指定这个选项,如果要浏览诸如passwd文件,此文件各域以冒号作为分隔符,则必须指明-F选项,如:
awk -F: 'commands' input-file

第二种方式是将所有awk命令插入一个文件,并使awk程序可执行,然后用awk命令解释器作为脚本的首行,以便通过键入脚本名称来调用它。

第三种方式是将所有的awk命令插入一个单独文件,然后调用:
awk -f awk-scrīpt-file input-files(s)
-f选项指明在文件awk_scrīpt_file中的awk脚本,input_file(s)是使用awk进行浏览的文件名。


模式和动作

任何awk语句都由模式和动作组成。在一个awk脚本中可能有许多语句。模式部分决定动作语句何时触发及触发事件。处理即对数据进行的操作。如果省略模式部分,动作将时刻保持执行状态。模式可以是任何条件语句或复合语句或正则表达式。模式包括两个特殊字段 BEGIN和END。使用BEGIN语句设置计数和打印头。BEGIN语句使用在任何文本浏览动作之前,之后文本浏览动作依据输入文本开始执行。END语句用来在awk完成文本浏览动作后打印输出文本总数和结尾状态标志。

域和记录
使用$1,$3表示参照第1和第3域,注意这里用逗号做域分隔。如果希望打印一个有5个域的记录的所有域,可使用$0,意即所有域。
为打印一个域或所有域,使用print命令。这是一个awk动作

模式和动作
模式:两个特殊断 BEGIN和END
动作:实际动作大多在{}内指明


输出
1.抽取域
awk -F: '{print $1}' /etc/passwd

2.保存输出
awk -F: '{print $1}' /etc/passwd | tee user 使用tee命令,在输出文件的同时,输出到屏幕

使用标准输出
awk -F: '{print $1}' /etc/passwd >user3

4.打印所有记录
awk -F: '{print $0}' /etc/passwd

5.打印单独记录
awk -F: '{print $1,$4}' /etc/passwd

6.打印报告头
awk -F: 'BEGIN {print "NAME\n"} {print $1}' /etc/passwd

7.打印结尾
awk -F: '{print $1} END {print "this is all users"}' /etc/passwd


条件操作符
1.匹配
awk -F: '{if($1~/root/) print }' /etc/passwd      //{if($1~/root/) print}表示如果field1包含root,打印它

2.精确匹配
使用等号 ==
awk -F: '{if($3=="0") print }' /etc/passwd 

3.不匹配
!~
awk -F: '{if($1!~/linuxtone/) print }' /etc/passwd

!=
精确不匹配
awk -F: '{if($1!="linuxtone") print }' /etc/passwd

4.小于
<
5.小于等于
<=
6.大于
>
.........
7.设置大小写
awk '/[Rr]oot/' /etc/passwd

8.任意字符
awk -F: '{if($1~/^...t/) print}' /etc/passwd      //^...t表示第四个字幕是t

9.或关系匹配
awk -F: '{if ($1~/(squid|nagios)/) print}' /etc/passwd

10.行首
awk '/^root/' /etc/passwd       // ^root(行首包含root)

11.AND &&
awk -F: '{if($1=="root" && $3=="0") print}' /etc/passwd

12.OR ||

内置变量:
ARCC                                      命令行参数个数
ARGV                                      命令行参数排列
ENVIRON                                   支持队列中系统环境变量的使用
FNR                                       浏览文件的记录数
FS                                        置顶分隔符,等价于-F
NF                                        浏览记录的域的个数
NR                                        已读的记录数
OFS                                       输出域分隔符
ORS                                       输出记录分隔符
RS                                        控制记录分隔符

打印有多少行记录
awk 'END {print NR}' /etc/passwd

设置输入域到变量名
awk -F: '{name=$1; path=$7; if(name~/root/) print name  "\tpath is:" path}' /etc/passwd

域值比较操作
awk '{if($6<$7) print $0}' input-file

修改文本域只显示修改改记录
awk -F: '{if($1=="nagios") {$1="nagios server" ; print }}' /etc/passwd

文件长度相加
ls -l|awk '/^[^d]/ {print $9"\t" $5} {tot+=$5} END {print "total kb:"tot}'

内置的字符窜函数
gsub(r,s)                                                      在整个$0中用s替代r
gsub(r,s,t)                                                    在整个t中用s替代r
index(s,t)                                                     返回s中字符串t的第一位置
length(s)                                                      返回s长度
match(s,r)                                                     测试s中是否包含匹配r的字符串
split(s,a,fs)                                                  在fs上将s分成序列a
sub(s, )                                                       用$0中最左边也是最长的字符串替代
subtr(s,p)                                                     返回字符串s中从p开始的后缀部分
substr(s,p,n)                                                  返回字符串s中从p开始长度为n的后缀部分

1.gsub
awk 'gsub(/^root/,"netseek") {print}' /etc/passwd             将与root开头的root替换为netseek

awk 'gsub(/0/,2) {print}' /etc/fstab

awk '{print gsub(/0/,2) $0}' /etc/fstab                      

2.index
awk 'BEGIN {print index("root","o")}'  查询字符串root中o出现的第一位置

awk -F: '$1=="root" {print index($1,"o")" "$1}' /etc/passwd

awk -F: '{print index($1,"o") $1}' /etc/passwd

3.length
awk -F: '{print length($1)'} /etc/passwd

awk -F: '$1=="root" {print length($1)}' /etc/passwd

4.match (在ANCD中查找C的位置)
awk 'BEGIN {print match("ANCD",/C/)}'

5.split
返回字符串数组元素个数
awk 'BEGIN {print split("123#456#789", myarray, "#")}'

6.sub   只能替换指定域的第一个0
awk 'sub(/0/,2) {print }' /etc/fstab

7.substr
按照起始位置及长度返回字符串的一部分
awk 'BEGIN {print substr("www.linuxtone.org",5,9)}'  //第5个字符开始,取9个字符。

awk 'BEGIN {print substr("www.linuxtone.org",5)}'  //第5个位置开始,取后面的所有.

字符串屏蔽序列
\b                  退格键
\f                  走纸换页
\n                  新行
\r                  回车
\t                  tab
\c                  任意其他特殊字符
\ddd                八进制

很简单的例子
awk -F: '{print $1,"\b"$2,"\t"$3}' /etc/passwd 输出函数printf(注意是printf不是print,两者效果不同的)
printf函数拥有几种不同的格式化输出功能

printf修饰符
-                               左对齐
Width                        域的步长0表示0步长
.prec                          最大字符串长度,或小数点右边的位数


awk printf格式
%c                              ASCII字符
%d                              整数
%e                              浮点数,科学计数法
%f                               浮点数
%g                              awk决定使用哪种浮点数转换,e或者f
%o                              八进制数
%s                              字符串
%x                              十六进制数

1.字符串转换
echo "65" | awk '{printf"%c\n",$0}'

awk 'BEGIN {printf "%c\n",65}'

awk 'BEGIN {printf "%f\n",999}'

2.格式化输出
awk -F: '{printf "%-15s %s\n",$1,$3}' /etc/passwd

awk -F: 'BEGIN {printf"USER\t\tUID\n"} {printf "%-15s %s\n",$1,$3}' /etc/passwd

3.向一行awk命令传值
who | awk '{if ($1 == user) print $1 " you are connected to:" $2}' user=$LOGNAME

4.awk脚本文件 (在文件名字后面加后缀.awk方便区分)
#!/bin/awk -f
BEGIN{
    FS=":"
        print "User\t\tUID"
        print"____________________________"
}

{printf "%-15s %s\n",$1,$3}

END{
       print "END"

}