awk从简单到复杂

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了awk从简单到复杂相关的知识,希望对你有一定的参考价值。

1、语法和参数说明

语法

awk [options] 'script' var=value file(s)

awk [options] -f scriptfile var=value file(s)

awk [options] 'pattern{action}' FILE ....


选项参数说明:

-F fs or --field-separator fs

指定输入文件折分隔符,fs是一个字符串或者是一个正则表达式,如-F:。

-v var=value or --asign var=value

赋值一个用户定义变量。

-f scripfile or --file scriptfile

从脚本文件中读取awk命令。

-mf nnn and -mr nnn

对nnn值设置内在限制,-mf选项限制分配给nnn的最大块数目;-mr选项限制记录的最大数目。这两个功能是Bell实验室版awk的扩展功能,在标准awk中不适用。

-W compact or --compat, -W traditional or --traditional

在兼容模式下运行awk。所以gawk的行为和标准的awk完全一样,所有的awk扩展都被忽略。

-W copyleft or --copyleft, -W copyright or --copyright

打印简短的版权信息。

-W help or --help, -W usage or --usage

打印全部awk选项和每个选项的简短说明。

-W lint or --lint

打印不能向传统unix平台移植的结构的警告。

-W lint-old or --lint-old

打印关于不能向传统unix平台移植的结构的警告。

-W posix

打开兼容模式。但有以下限制,不识别:/x、函数关键字、func、换码序列以及当fs是一个空格时,将新行作为一个域分隔符;操作符**和**=不能代替^和^=;fflush无效。

-W re-interval or --re-inerval

允许间隔正则表达式的使用,参考(grep中的Posix字符类),如括号表达式[[:alpha:]]。

-W source program-text or --source program-text

使用program-text作为源代码,可与-f命令混用。

-W version or --version

打印bug报告信息的版本。


其中pattern包括以下几种:

地址定界 

模式(包括正则表达式)

表达式

BEGIN(命令执行前预处理操作)

END(命令执行后的操作)


pattern通过,才会执行{action},当然pattern也可以省去,不匹配只执行动作。


action:  

定义变量(数组)

语句(if、while、for)

输出(print、printf)


awk内置的变量:

NF : 当前处理行一共多少字段

FS : 输入字段分隔符,默认空格

OFS : 输出字段分隔符,默认空格 

NR : 目前awk所处理的是第几行数据

2、基本用法

示例1:

打印用户为apache和zabbix用户的用户名、UID、处理行的字段总数、输出行处于文件的第几行、输出符合条件的行最后一列

方法1:

# awk -F: 'BEGIN{OFS="*"} /^apache|^zabbix/ {print $1,$3,NF,NR,$NF}' /etc/passwd

zabbix*498*7*30*/sbin/nologin

apache*48*7*36*/sbin/nologin


方法2:

# awk 'BEGIN{FS=":";OFS="*"} /^apache|^zabbix/ {print $1,$3,NF,NR,$NF}' /etc/passwd

zabbix*498*7*30*/sbin/nologin

apache*48*7*36*/sbin/nologin


解析:

分隔符:有两种表示方法,如方法1所示使用-F跟分隔符的方式,方法2中和输出分隔符OFS一块放入BEGIN{}模块,默认输出分隔符是空格。


NF:

表示文件内容的列数,所以$NF就表示最后一列。


模式:

/^apache|^zabbix/ 就是模式的匹配,模式写入//就可以,表示匹配以apache或者zabbix开头的行。


BEGIN:

在awk实际工作之前执行一次

举例:

# awk 'BEGIN{FS=":"} {print $1,$3}' /etc/passwd

root 0

bin 1

...


# awk '{FS=":"} {print $1,$3}' /etc/passwd

root:x:0:0:root:/root:/bin/bash 

bin 1

...


可以看到第二个输出结果和第一个结果不一样,因为BEGIN的工作流程是这样的:1、没有BEGIN出现,不用事前执行一些动作;2、awk开始获取第一行数据,以FS值为分隔符,此时的FS是空的,$0变量保存整行数据,$1保存第一个字段数据,$2保存第二个字段数据.........一直到最后;3、awk开始执行动作,FS=":" ---> 显示$1,$3 ---> 获取第二行数据,以FS值冒号为分隔符............。


在FS赋值之间就已经把第一行数据获取完毕了。 所以 在有BEGIN的情况下,awk在获取数据之前会执行一次BEGIN的动作, 而且只有这一次。 那么END也就不难理解了,就是在操作完所有行数据以后所执行的一次动作。


示例2:

print和printf

# awk 'BEGIN{FS=":"}NR==5,NR==8{print $1,$3,"\t\t","This is",NR,"line"}' /etc/passwd

lp 4             This is 5 line

sync 5           This is 6 line

shutdown 6               This is 7 line

halt 7           This is 8 line


解析:

NR是表示第几行,上面就是第5行到第8行的定界

在print里面除了变量以外,其它字符都要加上引号。\t表示一个制表符TAB。不同的字段输出的时候会以输出字符分隔符隔开

除了表示字段数据的$0,$1,$2等,其他变量包括自定义变量都不用$号


但是可以明显感觉上面的排版有点乱,这里可以使用printf对输出内容进行格式化。


下面进行格式化输出

# awk 'BEGIN{FS=":"}NR==5,NR==8{printf "%-10s %5s %10s %2s %5s\n",$1,$3," This is",NR,"line"}' /etc/passwd

lp             4    This is  5  line

sync           5    This is  6  line

shutdown       6    This is  7  line

halt           7    This is  8  line


解析:

格式化常用格式化字符

\n 换行

        \t 水平TAB键


        %s    显示字符串。    数值也可以当作字符串显示

        %d,%i 十进制整数。

        %c    显示字符ASCLL码。

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

        %f    浮点数显示。

%n.mf        n表示包括小数点在内的长度,m表示小数点后的长度。

        %%    显示%自身。

        %u    无符号整数

修饰符:

        -    左对齐

        +    显示数值符号

        0    以0代替多余的空格。

这里需要注意的是%-10s %5s %10s %2i%5s\n这一段就是格式化语句,%-10s:表示10个字符宽度,“-”表示左对齐,printf不会自动换行,所以后面加了个\n。


示例3:表达式

匹配UID大于等于500的相应信息

# awk 'BEGIN{FS=":"}$3>=500{printf "%-10s %5s %10s %2s %5s\n",$1,$3,"This is",NR,"line"}' /etc/passwd

nfsnobody  65534    This is 23  line

nexus        500    This is 31  line

box          501    This is 32  line


示例4:添加说明

对上面的输出添加说明

# awk 'BEGIN{FS=":";printf "%-10s %5s %12s %17s\n","USER","UID","SHELL","DESCRIPTION"}/bin\/bash\>/{printf "%-10s %5s %15s %10s %2i%5s\n",$1,$3,$7,"This is",NR,"line"}' passwd

USER         UID        SHELL       DESCRIPTION

root           0       /bin/bash    This is  1 line

nexus        500       /bin/bash    This is 31 line

...


示例5:算数和自定义变量

计算同学总成绩

# cat test.txt

User    English   Math   Music   

zhangsan   85     90      83    

lisi     80      95     60    

zhouwu    66    77       98     

zhengwang   80   93    67      


# awk 'NR==1{printf "%-10s %7s %6s %6s %6s\n",$1,$2,$3,$4,"Total"}NR>=2{total=$2+$3+$4;printf "%-10s %7s %6s %6s %6s\n",$1,$2,$3,$4,total}' test.txt

User       English   Math  Music  Total

zhangsan        85     90     83    258

lisi            80     95     60    235

zhouwu          66     77     98    241

zhengwang       80     93     67    240


解析:

NR==1表示第一行在第五列定义了一个字符串“Total”,也就是定义了一个变量。

NR>=2之后的内容表示当行数大于等于2的时候,每一行的Total的值等于第二列第三列和第四列的值相加。


未完待续...


参考:

http://f.dataguru.cn/thread-509133-1-1.html


以上是关于awk从简单到复杂的主要内容,如果未能解决你的问题,请参考以下文章

css 从简单到复杂的动态效果,你值得拥有

LFU五种实现方式,从简单到复杂

Libevent使用例子,从简单到复杂

Libevent使用例子,从简单到复杂

[z]Libevent使用例子,从简单到复杂

从简单到复杂:Apache Kafka应用实例详解