awk笔记

一、文本处理工具三剑客

1、grep:文本过滤器,主要功能是指定模式,显示匹配的文本。

2、sed:流编辑器,主要功能是根据指定的模式,来编辑文件。

3、awk:报告生成器,主要功能是从文本文件中抽取符合条件的信息,并以特定格式显示出来。soleries上是nawk,linux上是gawk

二、awk用法与格式

awk [options] 'PARTTERN    { action }'      file1 file2...

三、awk的处理机制

awk根据定义的parttern一次从文件中依次取出一行文本,对其按指定的分隔符自动切片分开,每一个切片是一个位置变量,$0表示一整行文本。

四、awk的OPTIONS

-F:指定切片分隔符

五、awk的PARTTERN

awk 'program' input-file1 input-file2 ...

其中的program为:

pattern { action }

pattern { action }

...

5.1:常见的模式类型:

1、Regexp:正则表达式,格式为/regular expression/

案例:

如找到文件中开头是r的字段:

awk -F: /r/'{print $1}' /etc/passwd

2、expression:表达式,其值非0或为非空字符时满足条件,如:$1 ~ /foo/ 或$1 == "magedu",用运算符~(匹配)和~!(不匹配)。

案例:

找到文件中$3+1之后大于等于500的UID字段:

awk -F: '$3+1>=500{print $1,$3}' /etc/passwd

找到文件中能被bash匹配到的用户:

awk -F: '$7 ~ /bash/{print $1,$7}' /etc/passwd

3、Ranges:指定匹配范围,格式为pattern1,parttern2,最小匹配单位是一个字段,也就是一个切片。不能用单个字符匹配。

案例:

找到文件中$1是root的,到$1为halt结尾的中间字段:

awk -F: '$1~"root",$1~"halt"{print $1,$2,$3,$4,$5,$6,$7}' /etc/passwd

错误匹配:

awk -F: '/^r/,/h$/{print $1,$2,$3,$4,$5,$6,$7}' /etc/passwd

由于最小匹配单位是一个切片字段,所以以单个字符匹配是错误的。


4.1、BEGIN/END:特殊模式,仅在awk命令执行前运行一次或结束前运行一次

案例:

在输出的第一行打印一个表头,输出最后打印结束信息:

awk -F: 'BEGIN{print "User                  Bash\n------------------------------------"} {printf "%-20s %-10s\n",$1,$7}END{print "--------------------------------------\nEnd of report"}' /etc/passwd

4.2、如果BEGIN还要加模式的话,那么模式要写在BEGIN的后面。比如:

awk -F: 'BEGIN{printf "%-10s%-10s%-10s\n","user_name","user_id","user_bash"}$1~"root",$7~"bash"{printf "%-10s%-10s%-10s\n",$1,$3,$7}END{printf "\n%-10s\n","End Reporting."}' /etc/passwd


5、Empty(空模式):匹配任意输入行

案例:

没有任何模式的输出会对文件的每一行都做处理:

awk -F: '{printf "%-20s%-10s%-20s\n",$1,$3,$7}' /etc/passwd

六、awk的ACTION

1、print:打印指定的文本,多个文本之间用逗号分开,变量不需要加引号,自定义文本需要加引号。

2、printf:能够格式化字符串输出

  printf format item1,item2...

要点:

1、其与print命令的最大不同是,printf需要指定format

2、format用于指定后面的每个item的输出格式

3、printf语句不会自动打印换行符,\n

format格式的指示符都以%开头,后跟一个字符,如下:

%c:显示字符的ASCII码

%d,%i:十进制整数

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

%f:显示浮点数

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

%s:显示字符串

%u:无符号整数

%%:显示%自身

修饰符:

N:显示宽度

-:左对齐

+:显示数值符号

例如:

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

3、Expressions(表达式,支持赋值表达式、判断表达式):

4、Control statements(控制语句,支持if、for、while、case):

4.1

if语句:

语法:{if (condition) {then-body} else {else-body}}

列子1:

找到文件中$1是root的行,如果是root打印admin,不是root打印common user:

awk -F: '{if ($1=="root") printf  "%-15s %-10s\n",$1,"is admin user\n";else printf "%-15s %-10s\n",$1,"is common user"}' /etc/passwd

列子2:

统计文件中有多少个用户的uid大于500。

awk -F: -v sum=0 '{if ($3>500) {sum++}}END{print sum}'

4.2

while循环语句:循环字段的,需要对每一个字段都操作的时候才用的到while循环

语法:{while (condition) {statement1;statement2;...}}

列子1:

打印文件中的i<3的列,$1和$2。注意:计算表达式i++要放在action中,每次print完之后执行。

awk -F: '{i=1;while(i<3) {print $i;i++}}' /etc/passwd

列子2:

找到文件中每一个字段的字符长度大于等于4的字段。

awk -F: '{i=1;while(i<=NF) {if (length($i)>=4) {print $i};i++}}' /etc/passwd

4.3

do-while语句:和while一样,只不过do-while把要做的放在前面,条件放在后面。

语法:do {statement1,statement2...} while(condition)

列子1:

打印文件中$i<3的列,$1和$2,注意:计算表达式i++要放在action中,每次print完之后执行。

awk -F: '{i=1;do {print $i;i++} while(i<=3)}' /etc/passwd

4.4

for循环语句:

语法:for(variables assignment; condition; iteration process){statement1,statement2}

列子1:

打印文件中$i<3的列;$1和$2

awk -F: '{for(i=1; i<3; i++) {print $i}}' /etc/passwd

列子2:

打印文件中字符长度大于4的字段

awk -F: '{for(i=1; i<=NF; i++) {if(length($i)>4) {print $i}}}' /etc/passwd

4.4.2

for循环遍历数组:

语法:for(i in array) {statement1,statement2,...}

列子1:

awk -F: '$NF !~ /^$/{BASH[$NF]++}END{for(A in BASH) {printf "%15s:%i\n",A,BASH[A]}}' /etc/passwd

4.5

case语句:

语法:switch(expression) {case VALUE or /REGEXP/: statement1,statement2, ...default:statement1, ...}

注:case语句的用法学习中没有找到,等以后有了再补上。


4.6

break和continue

常用于循环或case语句中

注:缺少例子


4.7

next

提前结束对本行文本的处理,并接着处理下一行,例如:下面的命令将显示其ID号为奇数的用户

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

注意:由于next的作用,awk在处理if判断条件为true的行时,提前结束了,并处理下一行。所以显示ID号为奇数的用户。

5、Compound statements(复合语句):

6、Input statements(输入语句):

7、Output statements(输出语句):

8、awk的操作符:

6.8.1:算数操作符:

-x:负值

+x:转换为数值

x^y:次方

x*y:乘法

x**y:次方

x/y:除法

x+y:加法

x-y:减法

x%y:取模

6.8.2:字符串操作符

只有一个,而且不用写出来,用于实现字符串连接

6.8.3:赋值操作符

=

+=

-=

*=

/=

%=

^=

**=

++

--

需要注意的是,如果某模式为=号,此时使用/=/可能会有语法错误,应以/[=]/替代

6.8.4:布尔值

awk中,任何非0或非空字符串都为真,反之就为假

6.8.5:比较操作符

x < ytrue if x is less than y

x <= ytrue if x is less than or equal to y

x > ytrue if x is greater than y

x >= ytrue if x is greater than or equal to y

x == ytrue if x is equal to y

x != ytrue if x is not equal to y

x ~ ytrue if the string x matches the regexp denoted by y

x !~ ytrue if the string x does not match the regexp denoted by y

subscript in arraytrue if the aray array has an eliment with the subscript subscript

6.8.6:表达式间的逻辑关系符:

&&:逻辑与

||:逻辑或

6.8.7:条件表达式

a=3
b=4
a>b?a is max;b is max

相当于shell的:

if selector;then
if-true-exp
else
if-false-exp
fi

七、AWK中使用数组

9.1

array[index-expression]

index-expression可以使用任意字符串:注意,如果某数组元素事先不存在,那么在引用其时,awk会自动创建此元素并初始化为空串;因此,要判断某数组中是否存在某元素,需要使用index in array的方式。

遍历数组中的每一个元素语法:

for (var in array) {statement1, ...}

其中,var用于引用数组下标,而不是元素值:

例子1:

计算当前系统中每个连接状态的数量

netstat -ant |awk '/^tcp/{state[$NF]++} END{for(a in state) print a,state[a]}'

说明:

1、awk过滤出tcp开头的所有行并对其操作

2、创建一个state的数组,下标为ESTABLISHED和LISTEN,++表示找到一个下标,就在原来的基础上加1。

3、最后END表示,在处理完所有的行,循环数组,a是一个下标,即代表了ESTABLISHED和LISTEN。打印a(下标),和下标的值。

例子2:

计算nginx日志中每个IP访问了多少次

awk '{count[$1]++} END{for(ip in count) {print ip,count[ip]}}' /var/log/nginx/access.log

例子3:

计算nginx日志中每个IP访问每个资源的次数

awk '{count[$1,$7]++} END{for(ip in count) {printf "%-200s%d\n",ip,count[ip]}}' /var/log/nginx/access_cd.polyguide.com.cn.log

八、awk的内置变量


8.1:和记录相关的内置变量

1、FS:读取文本文件时,所使用的字段分隔符,和-F一样

2、OFS:指定输出分隔符

3、RS:指定换行符

4、ORS:指定输出换行符

8.2:和数据相关的内置变量

1、NR:awk命令到目前为止对所有文件已经处理过了的行数,比如第一个文件处理了100行,第二个文件处理到了21行,那么NR=121。叫做绝对计数

2、NF:记录当前行有多少个字段,也就是切片的。

3、FNR:与NR不同的是,FNR记录的是正在处理的文件处理到的行数,不管之前处理过多少文件,FNR是对于当前处理文件的行数。比如第一个文件处理了100行,第二个文件处理到了21行,那么NR=21。叫做各自计数

4、ARGV:

5、ARGC:


8.3:用户自定义变量

允许用户自定义变量,变量名命名规则和大多数编程语言相同,只能使用字母、数字和下划线,且不能以数字开头,awk变量名称区分字符大小写


变量赋值方法:

1、在awk中赋值

awk 'BEGIN{var="variable testing";print var}'

2、在命令行中赋值

awk -v test="hello awk" 'BEGIN{print test}'

九、awk的内置函数

length([string])

功能:返回string字符串字符的个数

substr(string,start [,length])

功能:取string字符串中的子串,从start开始,取length个:start从1开始计数

system(command)

功能:执行系统command并将结果返回至awk命令

systime()

功能:取系统当前时间

tolower(s)

功能:将s中的所有字母转为小写

toupper(s)

功能:将s中的所有字母转为大写



笔记缺少:AWK每个内置函数的列子、自定义函数的用法,包括(定义函数,调用函数,函数传参)。以后补上,忘大神勿喷。