您的位置:首页 > 其它

AWK学习笔记

2016-02-02 16:54 267 查看
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、BEGIN/END:特殊模式,仅在awk命令执行前运行一次或结束前运行一次
案例:
在输出的第一行打印一个表头,输出最后打印结束信息:
awk -F: 'BEGIN{print "User                  Bash\n------------------------------------"} {printf "%-20s %-10s\n",$1,$7}END{print "--------------------------------------\nEnd of report"}' /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每个内置函数的列子、自定义函数的用法,包括(定义函数,调用函数,函数传参)。以后补上,忘大神勿喷。
本文出自 “初心、始终” 博客,谢绝转载!
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: