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)}}'