awk程序由所谓的主输入(main input)循环组成。一个循环称作一个例程。awk允许编写两个特殊的例程,他们在任何输入被读取前和所有输入都被读取后执行。他们是BEGIN和END规则相关的过程,BEGIN和END过程都是可选的。BEGIN函数是在文本被输入之前进行的操作,END是在文本被处理完毕后执行的操作。所以awk语句由BEGIN+主输入+END组成。
记录和字段:awk假设它的输入是有结构的,而不是一串无规则的字符。默认它将每个输入行作为一条记录,而将由空格或制表符分隔的单词作为字段。连续的多个空格和/或制表符被作为一个分隔符。默认的字段分隔符为空格,默认的制表分格符为换行
awk语法:
1. awk arguments 'script' filename
2. awk arguments 'BEGIN{options}{script/command}{script/command}……END{options}' filename \\其中BEGIN和END是可选项
同sed一样,正则表达式也需要写在规则的前面以//包括,条件和循环可以加入主循环之内
arguments参数
-f 调用脚本
-F 改变字段分隔符,空格表示默认字段分隔符,也可以在脚本中指定域分隔符,通过系统变量FS来改变;其中\n为换行,\t为制表符
-v 调用系统变量,例如:awk -v a=$HOSTNAME {print a} test.txt
预定义变量
$0 当前所有字段
$1~$n 当前第n个字段
FS 分隔符 用法:awk 'BEGIN{FS=":"}{print $1}' /etc/passwd
RS 输入记录的分隔符 用法:awk 'BEGIN{RS=":"}{print $0}' /etc/passwd
OFS 输出分隔符,默认为空格
ORS 输出记录的分隔符
NF 字段个数 #注意,引用的时候直接使用NF即可,如果使用$NF,则表明取最未字段的值
NR 行号 用法:awk -F: '{print NR" : ",NF}' /etc/passwd
-v 指定自定义变量 用法:awk -v host=$HOSTNAME 'BEGIN{print host}'
操作符:
< 小于
> 大于
<= 小于等于
>= 大于等于
== 等于
!= 不等于
~ 匹配 用法: awk -F: -v reg='^/bin.*' '$7 ~ reg {print $0}' /etc/passwd
!~ 不匹配
&& 与
|| 或
! 非
表达式
常量:常量分为字符串型和数字型,字符串型在表达式中必须用引号括起来,字符串中可以使用转义序列,如\n等
变量:如a=b,a是一个变量的名字,=是赋值操作,b是一个字符串;变量区分大小写,变量名只能由数字字母下划线组成,而且不能以数字开头,变量不区分类型,使用前不必初始化。
常用的算数操作符:+-*/%,加减乘除取余,如echo `expr $RANDOM%100`,可以在100以内随机取数
常用的赋值操作符:
++ 给变量加1
-- 给变量减1
+= 给变量加等号之后的值,等于于=+
-= 给变量减等号之后的值
*= 给变量乘以等号之后的值
/= 给变量除以等号之后的值
%= 给变量取余
^= 取幂
printf--格式化打印
c ascii字符
d 十进制整数
f 浮点格式
s 字符串
x 无符号十六进制
以上为常见的格式化打印选项,常用举例
语法: %-width.precision format-specifier 例:
printf "%d\t%s\n" 100 world
printf "%-s\t%s\n" hello world \\横杠表示左对齐,没有横杠表示右对齐
printf "%*.*f\n" 5 3 2.2222 宽度5,小数点后精度为3,打印2.2222,显示结果为2.222
以下是一个awk语句,使用printf的实例,用来显示文件名称和大小,并且统计总大字和文件个数:
cat awk.txt
BEGIN{printf "%-10s\t%-10s\n","filename","size"}
{total+=$5;printf "%-10s\t%-10d\n",$9,$5}
END{printf "%s%d\b%-10s%d\n","total:",total,"num:",NR}
ll | grep total | awk -f awk.txt
经典数据统计用法:
awk -F: '{a[$NF]++}END{for(i in a){print i":"a[i]}}' /etc/passwd
条件、循环
条件语句:if 和expr
if条件语句格式:
if(expression) action1;[else action2]
while:
while(condition) action
for:
for(condition) action
示例:
while: awk -F: '{i=1;while(i<=NF){printf(" %d:%s ",i,$i);i++}{print " "}}' /etc/passwd
for: awk -F: '{for(i=1;i<=NF;i++){printf(" %d:%s ",i,$i)}{print " "}}' /etc/passwd
AWK的函数:
int(x) 返回x的整数部分的值
sqrt(x) 返回x的平方根
rand() 返回伪随机数r,其中0<=r<1
srand() 建立rand()新的种子数,如果没有指定就用当天的时间 awk 'BEGIN{srand();print rand()}'
sub(),gsub() 替换函数 echo "hello world world" | awk '{gsub("world","longlong");print $0}'
index(s,t) 返回t在字符串s中的位置,如果没有则返回0
length(s) 返回字符串长度,当没有给出s时,返回$0的长度
match(s,r) 如果正则表达式r在s中匹配到,则返回出现的起始位置,否则返回0
split(s,a,sep) 使用sep将字符串s分解到数组a中。默认sep为FS echo "00-11-22-33-44" |awk '{split($0,a,"-");for(i in a){print i":"a[i]}}'
tolower(s) 将字符串中所有的大写字母转换为小写
toupper(s) 与tolower相反
AWK的自定义函数:
awk 'function sum(n,m){total=n+m;return total}BEGIN{print sum(4,5)}'
AWK高级用法示例:
1. 获取IP地址(多个分隔符、匹配用法): ifconfig eth0|awk -F':| +' '/inet addr/{print $4}'
2. 统计网络连接数(数组,匹配,循环): netstat -an | awk '/^tcp/{state[$NF]++}END{for(i in state){print i"\t"state[i]}}'
3. 获取JAVA程序匹配内容列:ps aux | grep java| awk -F' +|=' -v reg='^.*base.*' '{for(i=1;i<=NF;i++)if($i~reg){print $(i+1)}}'