Chinaunix首页 | 论坛 | 博客
  • 博客访问: 850173
  • 博文数量: 180
  • 博客积分: 10029
  • 博客等级: 上将
  • 技术积分: 2185
  • 用 户 组: 普通用户
  • 注册时间: 2009-11-06 09:15
文章存档

2010年(133)

2009年(47)

我的朋友

分类: 系统运维

2010-02-14 17:37:42

E-mail:

Awk/Gawk 编程命令整理

(本博文旨在归纳awk/gawk的命令,前面的多篇博文中演示了 gawk 的使用,

 例如:

http://blog.chinaunix.net/u3/105477/showart_2088280.html

http://blog.chinaunix.net/u3/105477/showart_2088383.html

http://blog.chinaunix.net/u3/105477/showart_2088392.html

http://blog.chinaunix.net/u3/105477/showart_2088393.html )

1. 关于 awk 和 gawk 语言

       gawk是所开发的awk。

       awk 是一种程序语言,对于资料的处理具有很强的功能,可以使用很短的代码轻易地完成对文本档案做修改、分析、提取和比较等处理。 如果用C或Pascal等语言编写程序完成上述功能,需要花费较多的时间编写很长的代码。

一、调用AWK

一共有三种方法分别如下:

1.1   awk  [-F  field-separator] ‘commands’ input-file(s)

这里面的commands 是真正的AWK命令。其中 [-F域分隔符] 是可选的指定域分隔符

示例:awk –F ‘commands’ input-file

1.2   将所有awk命令插入一文件,并使awk程序可执行。

    相当于编写一个可执行SHELL脚本

1.3   将所有的AWK命令插入一个单独文件,然后调用

PS其中的-F设置好一个文本行的域分隔符号

二、示例

有一个文本内容如下:

M.Tan   05/99   48311   Green   8       40      44

J.Lun   06/99   48317   green   9       24      26

P.Bun   02/99   48      Yello   12      35      28

共有七个域。域与域之间是通过空格进行分隔开的。故不必用-F 选项处理

2.1 保存AWK输出

awk '{print $0}' grade.txt > out         覆盖同名文件

awk '{print $0}' grade.txt > >out        追加同名文件

2.2 保存的同时再打印输出

awk '{print $0}' grade.txt | tee out     表示在写入文件的同时也会一并打印输出来

2.3 使用标准输入

AWK脚本都是从标准输入中接受输入。

$ belts.awk < grade.txt         表示从此文件中输入进来处理

也可用管道  $grade.txt | belts.awk     表示将此文件丢到后面的AWK脚本处理

2.4 打印所有记录

awk '{print $0}' grade.txt

PS$0 将打印一整行出来

当用AWK遇到错误的时候如何排查:

1、  确保整个awk命令用单引号括起来

2、  确保命令内所有引号成对出现。

3、  确保用花括号括起来动作语句,用圆括号括起来条件语句

PS:条件语句是用if()  {} 组成一个集合进来

 

9.2.3 awk中正则表达式及其操作

我们这里面的正则表达式均使用斜线括起来。示例/Green/这样的形式

在调用AWK命令之前可以使用正则表达式做一些过滤

 

9.2.4 元字符

元字符如下:

\      ^      $     .      []     |      ()     *     +     ?

其中的 + ? 只适用于awk不适用于sedgrep

 

9.2.5 条件操作符

示例:

awk '{print $4}' grade.txt 

输出:

Green

green

Yello       字段从1开始的1 2 3 4 5 -F指定的进行分割处理

 

PS:哦 AWK是指定字段之间的分隔符了如果没有指定就是空白符了如果指定了就用指定的进行分割处理。然后分割完了之后就会得到一系列的域出来分别用$1 开始表示如果用$0则表示全部的内容都打印出来!

 

示例:awk '{if($4!~/green/) print $0}' grade.txt

输出:

M.Tan   05/99   48311   Green   8       40      44

P.Bun   02/99   48      Yello   12      35      28

PS

4、  确保整个awk命令用单引号括起来

5、  确保命令内所有引号成对出现。

6、  确保用花括号括起来动作语句,用圆括号括起来条件语句

(条件表达式是用() 括起来的)

 

9.2.6 小于

示例:awk '{if ($6<$7) print $0 "$1 try better at the next comp "}' grade.txt

输出:

M.Tan   05/99   48311   Green   8       40      44$1 try better at the next comp

J.Lun   06/99   48317   green   9       24      26$1 try better at the next comp

 

9.2.7 小于等于

输入:awk '{if ($6<=$7) print $0 "$1 try better at the next comp "}' grade.txt

输出:

M.Tan   05/99   48311   Green   8       40      44$1 try better at the next comp

J.Lun   06/99   48317   green   9       24      26$1 try better at the next comp

 

9.2.8 大于

输入:awk '{if ($6>$7) print $0 "$1 try better at the next comp "}' grade.txt

输出:P.Bun   02/99   48      Yello   12      35      28$1 try better at the next comp

 

9.2.9 设置大小写

可用[] 符号。示例awk '/[Gg]reen/' grade.txt

输出:

M.Tan   05/99   48311   Green   8       40      44

J.Lun   06/99   48317   green   9       24      26

 

9.2.10 或关系匹配

可以用| 表示或关系运算。类似于or运算符

不过一定要用() 括起来

 

输入:awk '$0~/(Yello|brown)/' grade.txt

输出:P.Bun   02/99   48      Yello   12      35      28

PS:|表示或运算符这个表示或者或者注意一下区别

 

复合模式:

&&  AND:      表示只有两边同时为真的时候才成立

||  OR:       表示只要有一个为真

!  

 

9.1.11 AND

输入:awk '{if ($1=="P.Bun" && $4 == "Yello") print $0}' grade.txt

输出:P.Bun   02/99   48      Yello   12      35      28

 

PSAWK编程与程序是一样的哦!

 

9.1.12 Or

表示程序中为or运算符。

输入:awk '{if ($1=="P.Bun" || $4 == "Yello") print $0}' grade.txt

输出:P.Bun   02/99   48      Yello   12      35      28

 

PS:以上列举了常用的运算符。可以应用于逻辑编程

 

9.2.6          AWK内置变量

PS:相当于程序中的内置变量值

表:

ARGC                      命令行参数个数

ARGV                      命令行参数排列

ENVIRON                   支持队列中系统环境变量的使用

FILENAME                  AWK浏览的文件名

FNR                       浏览文件的记录数

FS                        设置输入域分隔符。等价于命令-F选项

NF                        浏览记录的域个数

NR                        读的记录数

OFS                       输出域分隔符

ORS                       输出记录分隔符

RS                        控制记录分隔符

 

示例:

输入:awk 'END {print NR}' grade.txt

输出:3

PS:打印查看记录个数

  

9.2.7          操作符

常用的操作符如下列表

= += *= / = %= ^ =                     赋值操作符

?                                      条件表达操作符

| && !                                 并、与、非

~  !~                                  匹配操作符,匹配与不匹配(匹配即模糊概念)

< <=  = =  != >>                       关系

+ - * / % ^                            算术

++ --                                  前缀和后缀

示例:

awk '{name=$1;belts=$4;if(belts ~/Yello/) print name "is test"}' grade.txt

解释:可以将域变量赋给一个新变量,然后在后面引用进来!

输出:P.Bunis test

 

awk '{if($6<27) print $0}' grade.txt

解释:表示第几个字段的值提取出来进行比较条件符合就输出

输出:J.Lun   06/99   48317   green   9       24      26

 

awk 'BEGIN {BASELINE="27 " }{if($6 < BASELINE) print $0}' grade.txt

解释:可以在前面定义好变量然后在后面直接引用进来就行!

输出:J.Lun   06/99   48317   green   9       24      26

发现在一个AWK表达式中可以使用多个{}AWK表达式定义进来

 

修改数值域取值

命令:awk '{if($1=="M.Tan") $6=$6-10;print $1,$6,$7}' grade.txt

输出:

M.Tan 30 44

J.Lun 24 26

P.Bun 35 28           (可以将第6个值域少10)(符合条件的就修改过来)

PS:语句之间的分隔请用; 分号 。字符表示请用”” 双引号表示

但是这种修改并没有对原来的文件修改过。只是其缓冲区的内容变更过来!

 

IF语句中如果有超过多条记录的时候请记得用{} 括起来(非常类似于其他的编程语言)

示例:awk '{if($1=="M.Tan") {$1="M.J.Mod";print $1}}' grade.txt

输出:

M.J.Mod  (这就是将IF成立的语句全部放在{}中)

 

PSAWK语句中的IF语句与实际其他编程语言是相通的即将IF语句后面的内容放入到IF后面的{}中去!IF语句后面的多个语句之间请用; 进行分割处理

 

创建新的输出域

输入:

awk 'BEGIN{print "Name\t Difference"} {if($6<$7){$8=$7-$6;print $1,$8}}' grade.txt

输出:

Name     Difference

M.Tan           4

J.Lun           2

PS:在一条AWK语句中可以写多个{}分割开来处理的!而且可以创建新的字段域进来

还可以对新域创建新的名字出来

如下:

awk 'BEGIN{print "Name\t Difference"} {if($6<$7){diff=$7-$6;print $1,diff}}' grade.txt

对新建的域可以取个好的名字

 

累记统计某一列累加之和

输入:awk '(toa+=$6); END{print "total is :" toa}' grade.txt

输出:

M.Tan   05/99   48311   Green   8       40      44

J.Lun   06/99   48317   green   9       24      26

P.Bun   02/99   48      Yello   12      35      28

total is :99                                                 (统计第六列的字段取其和)

 

PS上面我们定义过了BEGIN关键字这又定义了END关键字。表示在打印输出之后的开始行是输入什么与结束行输入什么!

 

以上打印是将其记录全部都打印出来了。如果记录过多不是想要的结果那可以这样写:

awk '{(toa+=$6)}; END{print "total is :" toa}' grade.txt

 

PS:可以在AWK语句中使用正则表达式模式匹配

示例:ls -l |awk '/^-/ {print $9}'

表示前面的输出会经过一个正则匹配处理之后再打印出来的!

(即前面的正则表达式的作用就是为了匹配输出符合条件的内容出来)

 

OK!到此为止表达式什么的都学习完了。发现其语法跟其他的MS一样的。现在来看下其内置的函数。通过这些函数能够快速解决问题!

内置的字符串函数

       AWK内置字符串函数列表

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

Sprint(fmt,exp)                返回经fmt格式化后的exp

Sub(r,s)                       $0中最左边最长的子串代替s

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

Substr(s,p,n)                  返回字符串s中从p开始长度为n的后缀部分

 

PS:总体来讲与其他语言的字符串符数功能差不多的。现在详细整理下其使用方法

1、  gsub

表示替换一个字符串为另一个,使用正则表达式,/目标模式/,替换模式/

模式与替换掉的文本之间是用, 号进行分割的

示例:

输入:awk 'gsub(/48/,4880) {print $0}' grade.txt             即在AWK表达式中使用正则模式

输出:

M.Tan   05/99   4880311 Green   8       40      44

J.Lun   06/99   4880317 green   9       24      26

P.Bun   02/99   4880    Yello   12      35      28   (替换掉)

 

2、  index 查询字符串st出现的第一位置。必须要用双引号将字符串括起来。

输入:awk 'BEGIN {print index("Green","e")}' grade.txt         

     (得到其索引下标值)

输出:3

 

3、  返回所需字符串长度。

输入:awk '{if($1=="M.Tan") {print length($1) " " $1}}' grade.txt

输出:5 M.Tan

调用此字符串函数进来!

 

还有一种办法awk 'BEGIN {print length("this is a hello")}'  直接对一个字符串进行取函数

输出:15

 

4、  match

测试目标字符串是否包含查找字符的一部分。可以对查找部分使用正则表达式,返回值为成功出现的字符排列数。如果未找到返回0.

示例:awk 'BEGIN {print match("ANCS",/d/)}'

输出:0                表示目标字符串ANCS中不存在要找的字符值

 

输入:awk 'BEGIN {print match("ANCS",/S/)}'

输出:4                表示找到了要查找的字符位置为 4

 

5、  split

使用这个函数返回字符串数组元素个数。

工作方式如下:

如果一字符串包含指定分隔符可以将其划分为一个数组,便可用split指定分隔符及数组名

示例split(“AD2-125-56”,myarray,”-”)

这样myarray[1]    = “AD2”         返回了一个数组出来了!

 

6、  sub

使用这个函数发现并替换模式的第一次出现的位置

示例:

 

7、  substr

它按照起始位置及长度返回字符串的一部分。

输入:awk '$1 == "J.Lun" {print substr($1,1,2)}' grade.txt

输出:J.                      (相当于将一个字符串进行了分割输出)

 

AWK中使用的屏蔽序列(即表示转义过的字符)

\b    退格键                  \t     tab

\f     走纸换页               \ddd   八进制值

\n    新行                    \c    任意其他特殊字符

\r     回车键

 

介绍一下awk输出函数printf使用

处理格式化输出功能。如按列输出、左对齐、右对齐

语法:printf([格式控制字符],参数)

修饰符如下:

.                        左对齐

Width                    域的步长,用0表示0步长

.prec                    最大字符串长度,或小数点右边的位数

 

AWK中的printf格式

%c                       ASCII字符

%d                       整数

%e                        浮点数

%f                        浮点数

%g                       awk决定使用哪种浮点数转换ef

%o                       八进制

%s                        字符串

%x                       十六进制

 

常用的操作:

1、  字符转换

echo "65" | awk '{printf "%c\n",$0}'   使用了%c 的格式化参数

输出:A

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

输出:999.000000

PS:其格式化输出的格式为:printf([格式控制字符],参数)  printf(“%f\n”,999)

 

2、 格式化输出

输入:awk '{printf "%-15s %s\n",$1,$3}' grade.txt

输出:

M.Tan           48311

J.Lun           48317

P.Bun           48

PS:按照指定的格式进行输出来。表示格式化输出!

 

编写awk脚本文件

可以将awk脚本写入到一个文件再去执行。可以创建一个awk扩展名的文件出来

 

awk数组

输入:awk 'BEGIN{print split("123#456#789",myarray,"#")}'

打印:3

得到一个数组出来数组的内容:

Myarray[1] = “123”

 

遍历的方法:

For (ele in array) print array[ele]

输入:awk 'BEGIN{record="123#456#789"; split(record,myarray,"#")} END{for(i in myarray) {print myarray[i]}}' /dev/null

 

PS:注意要用 /dev/null  作为输入参数哦!要不然就不会输出

输出:

123

456

789

遍历数组的方法!

 

其它补充:

    在awk编程中, BEGIN模式后面跟一个操作模块,:BEGIN{...},awk处理输入文件里的任意行之 前执行该模块,其实不用任何输入文件就能测试一个BEGIN操作模块,因为直到BEGIN操作模块完成之后,awk才开始读取输入.BEGIN操作通常用 来改变OFS,FS,RSawk内制变量的值.
:
awk 'BEGIN{FS=":";OFS="\t";ORS="\n"}{print $0}' filename
    在处理输入文件之前,把域分隔符FS设定成冒号,输出域分隔符OFS设定成TAB,并把输出记录分隔符ORS设定成一个换行符
.
    END
模式不于任何输入行匹配,但是执行任何与END模式相关的操作.在所有输入行处理完成之后在处理END模式
.
:
awk 'END{print "some strings" NR }' filename
    在awk处理完成文件后再执行END模块,NR的值是度入的最后一条记录号.

E-mail:
阅读(3183) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~