Linux 第28,29天 awk
时间: 20180816
时间: 20180817
awk
运行方式
awk基本用法
awk的变量(内置变量和自定变量)
awk的输出命令print, printf
awk的操作符
PATTERN模式
常用的ACTION
控制语句
数组
awk容易出错的地方
awk是文本处理三剑客之一,其具有过程式编程语言,还支持条件判断,数组,循环等编程语言中
可以使用的功能。
运行方式
1. 命令行执行
awk
2. awk程序文件
awk -f /path/awk_script
3. awk脚本
#!/bin/awk -f
awk基本用法 awk [options] 'program' fiel1 file2...
program: PATTERN{ACTION STATEMENT}
PATTERN 模式
ACTION STATEMENT动作语句,可以是多个语够组成,各语句间使用分号分隔
如print; printf
option
-F[] 指明输入字段的分隔符,默认为空格
-v VAR_NAME=VALUE 变量赋值
-f /PATH/AWK_SCRIPT 指定awk脚本文件
awk在处理文件时也是一次读取一行文本,然后根据输入分隔符进行切片,切成n个片段,
然后将每一片都赋给awk内部一个变量当做值来保存,这些变量为$1,$2...一直到最后一个
,awk就可以对这些片段单独处理比如显示某一段,特定段,甚至可以对某些片段进行额外
的加工处理,统计,计数,运算等
awk的变量
内置变量
FS input Field Seperator 输入字段分隔符,默认为空白
如awk -v FS=':' '{print $1}' /etc/passwd
RS input Record Seperator 输入时的行分隔符,默认为换行符
OFS Output Field Seperator 输出时的字段分隔符,默认为空格
ORS Output Record Seperator 输出时行的分隔符,默认为换行符
NF Number of field in current record 当前行的字段数
NR Number of Records 行数,命令后跟的所有文件将统一合并记数
FNR 行数,各文件单独计数
FILENAME 当前正被awk读取的文件的文件名
ARGC awk命令行中的参数的个数
ARGV 数组,保存了命令行参数本身
ARGV[index]
ARGV[0] ARGV[1]
自定义变量
-v VAR_name=VALUE 变量名区分字符大小写
awk -v MYVAL=test '{print MYVAL}' /etc/fstab
在program中自定义变量
awk 'BEGIN{FS=":";f1=3}{print $f1}' /etc/passwd
awk的输出命令print, printf
用法 print item1,item2...
item: 字符串,用引号引用
awk '{print "hello","testword"}' /etc/fstab
变量 显示变量的值,可以直接使用变量的名进行引用
print var_name
数值 无须加引号
printf
语法 printf FORMAT, item1,item2,...
要点
1.必须提供FORMAT
2.与print语句不同,printf不会自动换行,需要显式指定换行符\n
3.FORMAT中需要分别为后面的每个item指定一个格式符,否则item无法显示
格式符: 都以%开头,后面跟单个字符
%c 显示字符的ASCII码
%d %i 显示字符为十进制整数
%e %E 科学计数法显示数值
%f 显示为浮点数
%g %G 以科学计数法或浮点数格式显示数值
%s 显示为字符串
%u 显示无符号整数
%% 显示%符号自身
修饰符 每一种格式都有一些修饰符
#[.#]
左边的# 用于指定显示宽度
右边的# 显示精度
+|-
+表示右对齐
-表示左对齐(默认)
awk -F ":" '{printf "%-15s%+15s\n",$1,$4}' /etc/passwd
awk的操作符
操作符有算术运算、字符操作符、赋值操作符、比较操作符、模式匹配操作符、逻辑操作符
条件表达式和函数调用
算术操作符: 用来实现运算如x+y,x-y,x*y,x^y,x/6,x%y
-x 负值
+x 转换为数值
echo | awk '{a=10;b=3;print a/b}'
字符操作符: 字符串连接
赋值操作符: 通常为变量赋值,赋值操作符有以下几种
=, +=, -=, *=, /=, %=, ^=
++, --
比较操作符: 字符串或者数值的大小比较
>, >=, <, <=, ==, !=
模式匹配操作符: 根据右侧的模式进行匹配操作
~ 是否能由右侧指定的模式所匹配
!~ 是否不能由右侧指定模式所匹配
awk -F ':' '{if($1~/^root/){print $0}}' /etc/passwd
逻辑运算符: 进行逻辑运算
&& 与运算
|| 或运算
awk -F ':' '{if($1~/^root/||$7~/bash$/){print $0}}' /etc/passwd
条件表达式
selector?if-true-expression:if-false-expression
awk -F ':' '{$3>=1000?UserType="CommonUser":UserType="AdminUser";
printf "%-15s%-15s%5i\n",UserType,$1,$3}' /etc/passwd
注意此为一条命令输出时需要连接起来哦
函数调用: 调用函数来进行数据处理
格式: function_name(argu1,ague2,...)
awk有很多内部函数详细可以查看man文档里,这里做个示例,不太会用,这个是可以输出
随机数的一个函数,但是如果重复运行还是原来的随机数不知道为何
awk '{printf "%f\n",rand()}' /etc/passwd
内部函数
数值函数 rand() 返回0-1之间的一个随机函数
字符串函数
length([s]) 返回指定字符串的长度
awk 'BEGIN{i="sdlkfjleka";print length(i)}'
sub(r,s[,t]) 基于r所表示的模式来匹配字符串t中的内容,将其第一次被
匹配到的内容替换为s所表示的字符串
awk 'BEGIN{i="I am a doctor";t="am not"; print
i,sub("am",t,i),i}'
gsub(r,s[,t]) 与sub类似前者只是第一次匹配到替换,这个是只要匹配到就替换
split(s,a[,r]) 以r为分隔符去切割字符串s, 并将切割后的结果保存至a表示的
数组中
awk '{split($0,abc,":");print abc[1]}' /etc/passwd
substr(s,i[,n])从s所表示的字符串中取子串,取法:从i表示的位置开始,取
n个字符
从第一个开始取4个字符
awk '{print substr($0,1,4)}' /etc/passwd
时间函数
strftime(format[,timestamp][,utc-flag])
format 格式和date +%后边的格式一样
timestamp 是一个时间从1970-01-01日到一个时间点表示为秒和date +%s
所显示的一样
utc-flag 表示时区如+8,-8
让ping命令显示时间
ping -W 1 172.20.0.1| awk '{print $0"\t"strftime("%H:%M:%S")}'
systime() 此函数专用来显示从1970-01-01 00:00:00至现在系统时间之间
所经过的秒数
ping -W 1 172.20.0.1 | awk '{ print $0"\t"
strftime("%H%F-%H:M:%S",systime(),-8) }' (两行一条 命令)
PATTERN模式,对哪些内容进行处理
1 空格式匹配所有
2 /regular expression/ 仅将ACTION应用于能够被Regular expression所匹配到的行
awk -F ":" '/bash$/{OFS="----------";print $1,$7}' /etc/passwd
3 relational expression 关系表达式,即结果为真、假的表达式,或者其结果能类同于
真或假的表达,一般来说,结果为非0或非空字符串即可类同为真,否则类同为假
awk -F ":" '$3>=1000{print $1,$3}' /etc/passwd
awk -F ":" '$1~/^root/{print $0}' /etc/passwd /etc/shadow
4 line ranges 指定匹配的行范围
startline,endline
awk -F ":" '1,10{print $1,$7}' /etc/passwd
5 BEGIN/END 两个特殊模式
BEGIN 在文件格式化操作开始之前事行执行的一次操作,通常用于输出表头或做出
一个预处理操作
END 在文件格式操作完成之后,命令退出之前执行一次操作, 通常用于输出表尾或
做出清理操作
awk -F ":" 'BEGIN{printf "%-15s%-15s%15s\n","UserType","UserName",
"UserID"}{$3>=1000?UserType="ComUser":UserType="AdmUser";printf
"%-15s%-15s%15d\n",UserType,$1,$3}END{print "That is all User on
this Machine"}' /etc/passwd
此四行为一条命令,需要连接起来
常用的ACTION
1 EXPRESSION 例如变量赋值
2 Control Statements 控制语句,如if while等
3 Conpound Statements 复合语句
4 Input statements
5 output statements
控制语句
if(condition){statements}[else{statements}]
while(condition){statements}
do{statements}while(condition)
for(expr1,expr2,expr3){statements}
switch(expression){case VALUE or /REGEXP/:STATEMENT;...;default:statementN}
break
continue
delete array[index]
delete array
exit[expression]
if-else
语法 if(condition){statements}[else{statements}]
awk -F ":" '{if($3>=1000){print "CU",$1,$3}else{print "AU",$1,$3}}'
/etc/passwd(和前边是一条命令)
while循环
语法 while(condition){statements}
条件为真时循环,为假时退出循环
通常用于在当前行的各个字段间进行循环
awk '{i=1;while(i<=NF){if(length($i)>=6){print $i};i++}}' /etc/issue
输出/etc/issue文档中空格隔开的大于或等于6个字符长度的字段
do-while循环
语法do{statements}while(condition)
意义和前边的类似只是他会先执行一次语句后然后再进行条件判断
for循环
语法 for(expr1,expr2,expr3){statements}
awk '{for(i=1;i<=NF;i++){if(length($i)>=6){print $i}}}' /etc/issue
输出/etc/issue文档中空格隔开的大于或等于6个字符长度的字段
第二种用法用于遍历数组
for (var_name in ARRAY){print var_name,ARRAY[var_name]}
break and continue
break [n] 退出当前循环,n是一个数字用于指定退出几层循环
continue 提前结束本轮循环而进入下一轮
next 提前结束对本行文本处理,而提前进入下一行的处理操作
awk -F ":" '{if($3%2==0)next;print $1,$3}' /etc/passwd
数组
关联数组array[index-expression]
index-expression 可以使用任意字符
如果数组元素事先不存在,则在引用时,awk会自动创建此元素并将其值初始化为空串; 因此
若要判断数组中的某元素是否存在,要使用"index in array"的方式进行判断
数组遍历 要遍历数组中的元素,则要使用for(var_name in array)的方式进行,此时
var_name会遍历array的每个索引,所以,要显示数组元数的值,要使用array[var_name]
如 统计指定文件中所有行中每个单词出现的次数
awk '{for(i=1;i<=NF;i++)count[$i]++}END{for(s in count)print s,count[s]}'
test.log | sort -t' ' -k2 -rn(两行为一个命令)
统计tcp各连接状态数量
ss -ta| awk '!/^State/{i=1;count[$i]++}END{for(s in count)print s,count
[s]}'
awk容易出错的地方
1. program中字符串要尽量使用双引号,有时候单引号不认(个人感觉是C语言的原因)
2. 出现使用{}时一次输入一对,否则输入的多了出错几率大
3. 逻辑思维一定要强,要不然蒙哈哈