码迷,mamicode.com
首页 > 其他好文 > 详细

awk

时间:2015-05-15 01:28:37      阅读:319      评论:0      收藏:0      [点我收藏+]

标签:awk

awk命令:

Linux文本处理三剑客:

grep, egrep, fgrep: 文本过滤器

sed: 行编辑器

模式空间,保持空间

awk: 报表生成器,格式化文本输出

 

AWKa.k.a Aho, Weinberger, Kernighan

将文件的一行读入,并将其分隔为多段,用$1..位置变量表示,$0表示全部段

GNU awk = gawk

 

基本用法:

gawk [options] ‘program‘ file file ...

program: PATTERN { ACTION STATEMENT }

PATTERN省略表示对整个文件的每行文本执行后面的操作,由语句组成,语句分隔符是;

 

ACTION: print, printf

 

选项:

-F[]:指明输入字段分隔符;

-v var_name=value: 变量赋值

 

例: gawk -F: ‘{print $1,$3}‘ /etc/passwd

 

1awk的输出命令print

 

print item1, item2, ...

要点:

(1) item间使用逗号分隔,而输出时则使用输出分隔符分隔;

(2) 输出的各item可以字符串或数值、当前记录的字段($n)、变量或awk的表达式;数值会被隐式转换为字符进行输出;

(3) print后面的item如果省略,相当于print $0;  输出“空白”,使用print "";

 

2、变量                        

2.1 内置变量

FS input field seperator输入字段分隔符默认为空白字符;

技术分享

RSinput record separator, 输入行分隔符默认为换行符;

例:awk -v RS=[" "/] ‘{pirint $0}‘ /etc/passwd

表示输出/etc/passwd文件,换行符为空白或/

OFS output field seperator字段分隔符默认为空白字符;默认为空白字符;

技术分享

ORSoutput record separator,行分隔符默认为换行符;

例:把用户名输出为一行

技术分享

NF: number of field in current record当前行的字段数;

技术分享

NR行数,所有文件统一计数;

技术分享

FNR行数,各文件分别计数;

技术分享

FILENAME:当前文件名;

 

ARGC:命令行参数的个数;

例:awk ‘{print ARGC}‘ /etc/passwd

>2

awk ‘{print ARGC}‘ /etc/passwd /etc/issue

>3

ARGV:数组,保存了命令行参数;

例:

[root@MYPC ~]# awk ‘{print ARGV[0]}‘ /etc/issue

awk

[root@MYPC ~]# awk ‘{print ARGV[1]}‘ /etc/issue

/etc/issue

 

2.2 自定义变量

定义变量的位置:

(1) 可以program中定义变量;

(2) 通过-v选项定义变量;

变量名区分字符大小写

技术分享

 技术分享 

3printf命令

 

格式: printf format, item1, item2, ...

 

要点:

(1) format是必须的;

(2) 不会自动换行,需显式给定行分隔符\n

(3) format中需要分别为后面的每个item指定一个格式符;

 

格式符:都以%开头,后跟一个字符

%c: 显示字符的ASCII码;

%d%i: 显示十进制整数;

技术分享

 

技术分享

%e, %E: 科学计数法显示数值;

%f: 显示为浮点数;

%g, %G: 以科学计数法格式或浮点数格式显示数值;

%s: 字符串

%u: 无符号的整数

%%: 显示%自身

 

修饰符:

#[.#]: 第一个#指定显示宽度,例如%30s表示用30个字符长度去显示后面的字符串;第二个#表示小数点后的精度;

技术分享

 

技术分享

- 左对齐

技术分享

+:显示数值正负符号

 

4、操作符:

算术操作符:

x+y, x-y, x*y, x/y, x^y, x%y

-x: 负值

+x: 转换为数值

 

字符串操作:字符串连接

 

赋值操作符:

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

++, --

 

比较操作符:

>, >=, <. <=, ==, !=

 

模式匹配符:

~

!~

 

逻辑操作符:

&&

||

 

条件表达式:

selector?if-true-expression:if-false-expression

 

例:# awk -F: ‘{$3>=500?usertype="common user":usertype="sysuser or admin";printf "%20s:%-s\n",$1,usertype}‘ /etc/passwd

 

函数调用:

function_name(argu1,argu2,...)

 

5PATTERN

 

(1) /regular expression/: 仅处理能够被/regular expression/所匹配到的行;

技术分享

(2) relational expression:关系表达式,有真假之分,一般来说,其结果为非0或非空字符串时为“真”,否则,为“假”;

技术分享

表示第6个字段符合后面的模式就输出这一行

技术分享

(3) line ranges:行范围,类似sedvim的地址定界法;startline, endlinestartline和endline使用的是模式表达式

技术分享

(4) BEGIN/END: 特殊模式

仅在awk运行程序之前执行一次(BEGIN)或仅在awk运行程序之后执行一次(END);

如果只是显示/etc/passwd的账户和账户对应的shell,而账户与shell之间以逗号分割,而且在所有行添加列名name,shell,在最后一行添加"blue,/bin/nosh"

cat /etc/passwd |awk  -F ‘:‘  ‘BEGIN {print "name,shell"}  {print $1","$7} END {print "blue,/bin/nosh"}‘

name,shell

root,/bin/bash

daemon,/bin/sh

bin,/bin/sh

sys,/bin/sh

....

blue,/bin/nosh

 

awk工作流程是这样的:先执行BEGING,然后读取文件,读入有/n换行符分割的一条记录,然后将记录按指定的域分隔符划分域,填充域,$0则表示所有域,$1表示第一个域,$n表示第n个域,随后开始执行模式所对应的动作action。接着开始读入第二条记录······直到所有的记录都读完,最后执行END操作。

 

(5) empty: 空模式,匹配任意行;

 

 

6、常用的action

 

(1) Expressions 表达式

(2) Control statements 控制语句,如if

(3) Compound statements 复合语句

(4) input statements 输入语句

(5) output statements 输出语句

 

7、控制语句

 

if (condition) statement [ else statement ]

while (condition) statement

do statement while (condition)

for (expr1; expr2; expr3) statement

for (var in array) statement

break

continue

delete array[index]

delete array

exit [ expression ]

{ statements }

 

7.1 if-else

 

语法:if (condition) statement [ else statement ]

if (condition) { statements; } [ else { statements; }]

 

# awk -F: ‘{if ($3>=500) {print $1," is a common user.";} }‘ /etc/passwd

# awk -F: ‘{if ($3>=500) {print $1," is a common user.";} else {print $1," is a system user or admin.";}}‘ /etc/passwd

# awk ‘{if (NF>6) print NF, $0 }‘ /etc/inittab

 

用法:对awk取得的整行或行中的字段做条件判断;

 

7.2 while循环

语法:while (condition) statement

while (condition) { statements }

条件为真时进行循环,直到为假退出;

 

用法:通常用于在当前行的各字段间进行循环;

 

# awk ‘{i=1;while(i<=NF){printf "%20s:%d\n",$i,length($i); i++}}‘ /etc/inittab

# awk ‘{i=1;while(i<=NF){if(length($i)>4){print $i,length($i)}i++;}}‘ /etc/inittab             length是个内置获取字符串长度的函数

 

7.3 do-while循环

语法:do statement while (condition)

do { do-while-body }  while (condition)

意义:至少执行一次循环体;

 

7.4 for循环

语法:for (expr1; expr2; expr3) statement

for (expr1; expr2; expr3) { statements }

 

for (varaiable assignment; condition; iteration process) { for-body }

 

# awk ‘{for(i=1;i<=NF;i++) {printf "%s:%d\n", $i, length($i)}}‘ /etc/inittab

 

for循环在awk中有一个专用于遍历数组元素:

语法:for (var in array) { for-body }

{for(i in array){print aarray[$i]}}‘

 

7.5 switch

语法:switch (expression) {case VALUE or /REGEXP/: statement; ...; default: statementN}

 

7.6 break and continue

break [n]: 退出当前循环

continue:提前结束本轮循环,直接进入下轮循环

 

7.7 next

提前结束对本行的处理而进入下一行的处理

 

取出UID为偶数的用户名和UID

#awk -F:‘{if($3%2==0){print $1,$3;}}‘ /etc/passwd

# awk -F: ‘{if($3%2!=0) next;print $1,$3}‘ /etc/passwd

 

8Array

 

关联数组:array[index-expression]

 

index-expression:

可以使用任意字符串;

如果某数组元素事先不存在,在引用时,awk会自动创建此元素并将其值初始化为空串;

因此,若要判断数组是否存在某元素,要使用“index in array”进行;

 

a[mon]="Monday"

print a[mon]

 

要遍历数组中的每个元素,使用: for (var in array) { for body }

 

 注意:var会遍历array的每一个索引,print array[var]

 

例:统计每一行中各单词分别出现的次数

~]# awk ‘{for(i=1;i<=NF;i++) {count[$i]++}}END{for(j in count) {print j,count[j]}}‘ awk.txt

 

~]# ss -tan | awk ‘!/^State/{state[$1]++}END{for (i in state) {print i,state[i]}}‘

~]# netstat -tan | awk ‘/^tcp/{state[$NF]++}END{for(i in state){print i,state[i]}}‘

 

练习:统计httpd访问日志中,每个IP出现的次数;

~]# awk ‘{ip[$1]++}END{for(i in ip){print i,ip[i]}}‘ /var/log/httpd/access_log

 

9、函数

 

9.1 内置函数

数值处理:

rand() 返回01之间一个随机数;

 

字符串处理:

length([s]) 返回指定字符串的长度

sub(r, s [, t]):以r所表示的模式来查找t字符串中的匹配,将其第一次出现替换同s所表示的字符串;

sub(ab,AB,$0)

gsub(r, s [, t]):以r所表示的模式来查找t字符串中的匹配,将其所有的出现均替换同s所表示的字符串;

split(s, a [, r]): r为分隔符切割字符串s,并将切割的结果保存至a表示数组中;返回字段的个数

 

~]# netstat -tan | awk ‘/^tcp/{len=split($5,client,":");ip[client[len-1]]++}END{for(i in ip){print i,ip[i]}}‘

 

substr(s, i [, n]) s表示的字符串中取子串,从i开始,取n个字符;

 

时间类的函数:

systime(): 取时间戳;

 

位运算函数:

and(v1,va2):

 

9.2 自定义函数

function f_name(p,q)

{

...

}


本文出自 “xxlixin” 博客,请务必保留此出处http://xxlixin1993.blog.51cto.com/9498220/1651399

awk

标签:awk

原文地址:http://xxlixin1993.blog.51cto.com/9498220/1651399

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!