awk:
文本处理三剑客:grep系,sed,awk
grep系:grep,egrep,fgrep,基于PATTERN进行文本过滤;
sed:流编辑器,逐行编辑器;模式空间,保持空间;
awk:报告生成器;格式化文档输出;web
awk是下面三我的的姓氏缩写: 最先由Alfred Aho开发的,曾工做于贝尔实验室; Peter J Weinberger:贝尔实验室; Brian W Kernighan:贝尔实验室;K&R这两我的共同编写了 《C语言程序设计 第二版》 被各类改版的awk: CentOS/RHEL系:GNU awk,gawk; New awk,nawk; Old awk,oawk; gawk命令: gawk - pattern scanning and processing language 格式: gawk [ options ] 'program' file ... program:[/PATTERN/]{ACTION statement; ...} PATTERN部分:决定动做语句什么时候触发以及经过什么事件来触发; BEGIN, END ACTION statement:对数据进行特定的处理,一般放置在{}中; print, printf 基本概念: 分隔符: 输入分隔符: awk对数据进行处理时,会根据特定的标识符号对数据进行分段处理,这种标识符号就称为"输入分隔符",默认的输入分隔符是空白字符;若是指定的分隔符并无被数据包括,则只有换行分隔符有效; 输出分隔符: awk对数据处理完成后,会以特定的标识符号对各个字段进行链接后输出,这种标识符号就称为"输出分隔符",默认的输出分隔符是空白字符; 记录:由换行符进行分隔的数据中一行,就称为一条记录(Record);一般在使用awk处理数据时,使用内置变量$0来保存整个记录的内容; 字段:通过分隔符分隔以后的每个数据分段,都称为一个字段(Field);一般在使用awk处理数据时,使用$1,$2...$NF(Number of Field)等内置变量来存储各个字段的数据; awk的工做原理: 1.首先,执行BEGIN{ACTION statement;...}语句块中的语句; 2.其次,从文件中或着标准输入读取一行,根据PATTERN的匹配结果执行后面的ACTION语句块中的内容;而后逐行重复该过程已完成数据处理,直到数据所有被读取完毕; 3.最后,在全部的语句块都执行完成以后,退出awk进程以前,执行END{ACTION statement;...}语句块中的语句; 注意: 1) BEGIN语句块在awk开始处理数据内容以前就被执行;一般用于生成表头;此语句块是可选语句块; 2) END语句块在处理完全部的数据以后,才会被执行;一般用于数据汇总;此语句块是可选语句块; 3) PATTERN语句块中的通用命令是最重要的部分,所以PATTERN语句块不能省略,但其中的ACTION能够省略,若是省略,则默认执行print动做,即:显示数据的各行; 4) awk在执行PATTERN语句块时,默认循环遍历数据中的各个记录; 经常使用选项: -f,--file program-file:从指定的文件中加载program语句块,而不是经过命令行给出相关的程序内容; -F,--field-separator fs:指定字段的输入分隔符;默认是空白字符; -v,--assign var=val:用于声明自定义变量并为变量赋值; awk的经常使用用法: 1.变量: 内建变量: FS:input field separator,输入字段分隔符,默认为空白字符; OFS:output field separator,输出字段分隔符,默认为空白字符; 示例: ~]# awk -v FS=':' -v OFS=':' '{print $1,$3,$7}' /etc/passwd root:0:/bin/bash bin:1:/sbin/nologin daemon:2:/sbin/nologin ... RS:The input record separator,输入记录(行)分隔符,默认为换行符; 注意:即便指定了额外的输入记录分隔符,原有的换行符依然有效; ORS:The output record separator,输出记录分隔符,默认为换行符; 示例: ~]# awk -v RS=':' -v ORS='#' '{print $0}' /etc/passwd root#x#0#0#root#/root#/bin/bash bin#x#1#1#bin#/bin#/sbin/nologin daemon#x#2#2#daemon#/sbin#/sbin/nologin adm#x#3#4#adm#/var/adm#/sbin/nologin lp#x#4#7#lp#/var/spool/lpd#/sbin/nologin ... NF:The number of fields,每一行中的字段的总数; 示例: ~]# awk -F: '{print NF}' /etc/passwd 7 7 7 7 7 ... 显示指定文件中每行中的字段的数量; ~]# awk -F: '{print $NF}' /etc/passwd /bin/bash /sbin/nologin /sbin/nologin /sbin/nologin /sbin/nologin /bin/sync ... 显示指定文件中每行中最后一个字段的内容; ~]# awk -F: '{print $(NF-1)}' /etc/passwd /root /bin /sbin /var/adm /var/spool/lpd /sbin /sbin ... 显示指定文件中每行中倒数第二个字段的内容; NR:The total number of input records,行的总数;若是仅处理一个文件,能够将NR的值看成此文件中各行的行号; 示例: ~]# awk '{print NR}' /etc/fstab 1 2 3 4 5 ... FNR:The input record number in the current input file,对于不一样的文件分别统计其行的数量;即便处理多个文件,也能够显示每一个文件中每行的行号; 示例: ~]# awk '{print FNR}' /etc/fstab /etc/issue 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 1 2 3 FILENAME:The name of the current input file,当前正在被处理的文件的文件名; 示例: ~]# awk 'END{print FILENAME}' /etc/fstab /etc/fstab ARGC:The number of command line arguments,命令行中参数的数量;包括awk命令自己,但不包括awk命令的选项部分和program部分; 示例: ~]# awk 'END{print ARGC}' /etc/fstab /etc/issue /etc/passwd 4 ARGV:Array of command line arguments,由命令行中全部的参数构成的数组; 示例: ~]# awk 'END{print ARGV[1]}' /etc/fstab /etc/issue /etc/passwd /etc/fstab 显示命令行中的第N个参数; 自定义变量: 定义方式: -v var_name=value 注意:变量名字母大小写敏感的; 示例: ~]# awk -v var='hello' -F: '{print $1"," var}' /etc/passwd root,hello bin,hello daemon,hello adm,hello ... 经常使用的ACTION: 2.print:Print the current record,以标准格式输出结果; 格式: print item1,item2,... 注意: 1) 各item之间须要使用","进行分隔; 2) 输出的各item能够是字符串,能够是数字,能够是当前记录中的字段,能够是变量,能够是awk的表达式; 3) 若是省略了item,则默认的item为$0,即:输出整行; 示例: ~]# awk '{print}' /etc/issue CentOS release 6.9 (Final) Kernel \r on an \m ~]# awk '{print $1,$3,$NF}' /etc/issue CentOS 6.9 (Final) Kernel on \m 3.printf:Format and print,以特定的格式输出结果; 格式: printf "FORMAT" item1,item2,... 注意: 1) 必须给出合适的输出格式; 2) 默认不会自动换行,若是想要在输出结果中换行显示,须要显式给出换行控制符号,即:\n; 3) FORMAT中须要为后面的每个item单独指定一个格式化符号; 经常使用的FORMAT:%number+字母 标识这么多个数字的字符以%字母格式显示 例:%20s %c:以ASCII码表中的内容显示字符信息; %d, %i:显示十进制整数; %e, %E:以科学计数法来显示数字;浮点类型; %f, %F:显示十进制数字的浮点形式; %g, %G:以科学计数法显示浮点数字; %u:显示无符号十进制数; %s:显示字符串; %x, %X:显示无符号的十六进制整数; %%:显示%; 修饰符: #[.#]:第一个数字用来控制显示宽度;第二个数字表示小数点的精度; 如:%5s, $8.3f -:表示采用左对齐方式显示;默认是右对齐; +:显示数字的正负符号; 示例: ~]# awk -F: '{printf "%20s:%-+5d\n",$1,$3}' /etc/passwd root:+0 bin:+1 daemon:+2 adm:+3 lp:+4 ... 4.操做符: 算术运算操做符: 双目运算符必须用两个数字进行运算: x+y, x-y, x*y, x/y, x^y, x%y 单目运算符: -x:将正整数转换为负整数; +x:将字符串转换为数值; 单目运算符的优先级高于双目运算符 示例:这个示例就是个运算而已后面参数是哪一个文件已经无所谓了 ~]# awk -F : 'END{print 100^2}' /etc/passwd 字符串操做符: 无任何操做符号时,即为字符串链接操做; 赋值操做符: =, +=, -=, *=, /=, ^=, %= ++, -- 比较操做符: ==, !=, >, >=, <, <= 示例:找到用户UID为1000的并打印出其用户名 ~]# awk -F : '$3>=1000{print $1}' /etc/passwd nfsnobody 模式匹配操做符: ~:操做符左侧的字符串是否可以被右侧的PATTERN所匹配; !~:操做符左侧的字符串是否不能被右侧的PATTERN所匹配; 示例: ~]# awk -F : '$NF~/bash/{print $0}' /etc/passwd root:x:0:0:root:/root:/bin/bash 逻辑运算操做符: && || ! 示例: ~]# awk -F: '$3>=1000&&$3<=1000000{print $0}' /etc/passwd nfsnobody:x:65534:65534:Anonymous NFS User:/var/lib/nfs:/sbin/nologin 条件表达式: selector(condition)?if-true-expression:if-false-expression 示例: ~]# awk -F: '{$3>=1000?usertype="Common User":usertype="SuperUser or Sysuser";printf "%20s: %-20s\n",$1,usertype}' /etc/passwd root: SuperUser or Sysuser bin: SuperUser or Sysuser daemon: SuperUser or Sysuser adm: SuperUser or Sysuser lp: SuperUser or Sysuser sync: SuperUser or Sysuser shutdown: SuperUser or Sysuser halt: SuperUser or Sysuser mail: SuperUser or Sysuser uucp: SuperUser or Sysuser operator: SuperUser or Sysuser games: SuperUser or Sysuser gopher: SuperUser or Sysuser ftp: SuperUser or Sysuser nobody: SuperUser or Sysuser dbus: SuperUser or Sysuser usbmuxd: SuperUser or Sysuser rpc: SuperUser or Sysuser rtkit: SuperUser or Sysuser avahi-autoipd: SuperUser or Sysuser vcsa: SuperUser or Sysuser abrt: SuperUser or Sysuser rpcuser: SuperUser or Sysuser nfsnobody: Common User haldaemon: SuperUser or Sysuser ntp: SuperUser or Sysuser apache: SuperUser or Sysuser saslauth: SuperUser or Sysuser postfix: SuperUser or Sysuser gdm: SuperUser or Sysuser pulse: SuperUser or Sysuser sshd: SuperUser or Sysuser tcpdump: SuperUser or Sysuser named: SuperUser or Sysuser 5.PATTERN部分: 1) empty:空模式,不加区分地处理文件的每一行; 2) [!]/REGEXP/:仅处理[不]能被PATTERN匹配到的行; 示例: ~]# awk -F: '/^r/{print $0}' /etc/passwd root:x:0:0:root:/root:/bin/bash rpc:x:32:32:Rpcbind Daemon:/var/lib/rpcbind:/sbin/nologin rtkit:x:499:499:RealtimeKit:/proc:/sbin/nologin rpcuser:x:29:29:RPC Service User:/var/lib/nfs:/sbin/nologin ~]# awk -F: '!/n$/{print $0}' /etc/passwd root:x:0:0:root:/root:/bin/bash sync:x:5:0:sync:/sbin:/bin/sync halt:x:7:0:halt:/sbin:/sbin/halt 3) 关系表达式: $3>=1000 $NF~/bash/ 4) 行域,行范围: 关系表达式的逻辑运算:FNR>=10&&FNR<==20 示例: ~]# awk 'NR>=15&&NR<=20{print NR,$0}' /etc/passwd 15 nobody:x:99:99:Nobody:/:/sbin/nologin 16 dbus:x:81:81:System message bus:/:/sbin/nologin 17 usbmuxd:x:113:113:usbmuxd user:/:/sbin/nologin 18 rpc:x:32:32:Rpcbind Daemon:/var/lib/rpcbind:/sbin/nologin 19 rtkit:x:499:499:RealtimeKit:/proc:/sbin/nologin 20 avahi-autoipd:x:170:170:Avahi IPv4LL Stack:/var/lib/avahi-autoipd:/sbin/nologin /REGEXP1/,/REGEXP2/: 从被REGEXP1匹配的行开始,直到被REGEXP2匹配的行结束,这期间的全部行;凡是属于此类的匹配结果,有多少组就显示多少组; 示例: ~]# awk -F: '/^r/,/^a/{print NR,$0}' /etc/passwd 1 root:x:0:0:root:/root:/bin/bash 2 bin:x:1:1:bin:/bin:/sbin/nologin 3 daemon:x:2:2:daemon:/sbin:/sbin/nologin 4 adm:x:3:4:adm:/var/adm:/sbin/nologin 18 rpc:x:32:32:Rpcbind Daemon:/var/lib/rpcbind:/sbin/nologin 19 rtkit:x:499:499:RealtimeKit:/proc:/sbin/nologin 20 avahi-autoipd:x:170:170:Avahi IPv4LL Stack:/var/lib/avahi-autoipd:/sbin/nologin 23 rpcuser:x:29:29:RPC Service User:/var/lib/nfs:/sbin/nologin 24 nfsnobody:x:65534:65534:Anonymous NFS User:/var/lib/nfs:/sbin/nologin 25 haldaemon:x:68:68:HAL daemon:/:/sbin/nologin 26 ntp:x:38:38::/etc/ntp:/sbin/nologin 27 apache:x:48:48:Apache:/var/www:/sbin/nologin 5) BEGIN/END模式: BEGIN{} 仅在开始处理文件中的第一行文本数据以前执行一次的语句块;多用于输出特定格式的表头信息; 示例: ~]# awk -F: 'BEGIN{printf "%20s %10s %20s\n","USERNAME","USERID","SHELL"}NR>=15&&NR<=20{printf "%20s %10s %20s\n",$1,$3,$7}' /etc/passwd USERNAME USERID SHELL nobody 99 /sbin/nologin dbus 81 /sbin/nologin usbmuxd 113 /sbin/nologin rpc 32 /sbin/nologin rtkit 499 /sbin/nologin avahi-autoipd 170 /sbin/nologin root: SuperUser or Sysuser bin: SuperUser or Sysuser daemon: SuperUser or Sysuser ... END{} 仅在文本处理完成但awk命令还没有退出时执行一次的语句块;多用于数据信息的汇总; 示例: ~]# awk -F: 'BEGIN{printf "%20s %10s %20s\n","USERNAME","USERID","SHELL"}NR>=15&&NR<=20{printf "%20s %10s %20s\n",$1,$3,$7}END{print "------------------------------------------------------------------\n",NR " users"}' /etc/passwd USERNAME USERID SHELL nobody 99 /sbin/nologin dbus 81 /sbin/nologin usbmuxd 113 /sbin/nologin rpc 32 /sbin/nologin rtkit 499 /sbin/nologin avahi-autoipd 170 /sbin/nologin ------------------------------------------------------------------ 34 users 注意: 1) BEGIN语句块,PATTERN语句块和END语句块的顺序,一般来说是: BEGIN{}PATTERN{}END{} 2) BEGIN语句块和END语句块是可选的,但PATTERN语句块必需要给出; 6.经常使用的ACTIONS 1) 表达式(Expression) 2) 组合语句(Compound Statements) 3) 输入语句(Input Statements) 4) 输出语句(Output Statements) 5) 控制语句(Control Statements) 7.控制语句: if (condition) statement [ else statement ] while (condition) statement do statement while (condition) for (expr1; expr2; expr3) statement for (var in array) statement break continue exit [ expression ] switch (expression) { case value|regex : statement ... [ default: statement ] } next 1) if ... else: 语法: if (condition) statement [ else statement ] 使用场景:对awk取得的整行或某个字段作条件判断; 示例: ~]# awk -F: '{if($3>=1000){print "CommonUser:",$1}else{print "Sysuser:",$1}}' /etc/passwd Sysuser: root Sysuser: bin Sysuser: daemon Sysuser: adm ... ~]# awk '/^[^#]/{if(NF==6){print}}' /etc/fstab /dev/mapper/VolGroup-lv_root / ext4 defaults 1 1 UUID=f1dc8baa-7d08-4d88-943c-339bae3704f9 /boot ext4 defaults 1 2 /dev/mapper/VolGroup-lv_home /home ext4 defaults 1 2 /dev/mapper/VolGroup-lv_swap swap swap defaults 0 0 tmpfs /dev/shm tmpfs defaults 0 0 devpts /dev/pts devpts gid=5,mode=620 0 0 sysfs /sys sysfs defaults 0 0 proc /proc proc defaults 0 0 /dev/raid_vg/raid_lv /userhome ext4 defaults 0 0 分析磁盘上各个文件系统的空间利用率: ~]# df -h | awk -F% '/^\/dev/{print $1}' | awk '{if($NF>=80){print $1}}' /dev/sr0 2) while循环: 语法: while (condition) statement 使用场景: a.对一行内的多个字段逐一作相同或相似的操做处理时使用; b.对数组中的各数组元素作遍历处理时使用; while循环的特色:条件为真,进入循环;一旦条件为假,则退出循环; 示例:判断字符串长度 ~]# awk '{i=1;while(i<=NF){print $i,length($i);i++}}' testfile The 3 first 5 day 3 when 4 I 1 started 7 my 2 middle 6 school 6 life, 5 I 1 felt 4 so 2 lonely, 7 because 7 I 1 didn’t 6 know 4 anyone 6 who 3 was 3 around 6 me. 3 3) do ... while语句: 语法: do statement while (condition) 意义:与while循环相同,但statement语句段至少被执行一次; 4) for循环: 语法: for (expr1; expr2; expr3) statement expr1:variable assignment,变量赋初值; expr2:circle condition,循环条件判断; expr3:interation process,变量值修正方法; 示例: ~]# awk '{for(i=1;i<=NF;i++){print $i,length($i)}}' testfile The 3 first 5 day 3 when 4 I 1 started 7 my 2 middle 6 school 6 life, 5 I 1 felt 4 so 2 lonely, 7 because 7 I 1 didn’t 6 know 4 anyone 6 who 3 was 3 around 6 me. 3 for (var in array) statement 5) switch ... case语句 语法: switch (expression) { case value|regex:statement;case value2|regex2:statement;... [ default: statement ] } 使用场景: 用于进行字符串比较判断; 6) break和continue语句: break [n] continue 注意:其使用场景是行内多个字段间作循环时的循环控制方式; 示例: ~]# awk '{for(i=1;i<=NF;i++){if(length($i)<5){continue}else{print $i,length($i)}}}' testfile first 5 started 7 middle 6 school 6 life, 5 lonely, 7 because 7 didn’t 6 anyone 6 around 6 7) next语句: 在awk处理数据时,提早结束对当前行的处理,而直接开始处理下一行; 示例: ~]# awk -F: '{if($3%2==1){next}else{print $1,$3}}' /etc/passwd root 0 daemon 2 lp 4 shutdown 6 mail 8 uucp 10 games 12 ftp 14 rpc 32 avahi-autoipd 170 nfsnobody 65534 haldaemon 68 ntp 38 apache 48 saslauth 498 gdm 42 sshd 74 tcpdump 72 或者用下面这种方式也是同样的 ~]# awk -F: '{if($3%2==1)next;print $1,$3}' /etc/passwd 8.数组——Array 用户自定义的数组,通常使用关联数组:array_name[index_expression] 注意: 1) index_expression可使用任意的字符串,但字符串必须放在双引号中; 2) 支持弱变量数组,即:若是某数组元素事先不存在,当引用该元素时,awk会自动建立此元素,并为此元素赋"空字符串"做为其初始值; 示例: ~]# awk 'BEGIN{name["leader"]="zhangsan";name["mem1"]="lisi";name["mem2"]="bob";print "Leader:",name["leader"],"Member:",name["mem1"],name["mem2"]}' Leader: zhangsan Member: lisi bob ~]# awk 'BEGIN{name["leader"]="zhangsan";name["mem1"]="lisi";name["mem2"]="bob";for(i in name){print name[i]}}' lisi bob zhangsan 查看当前系统上全部服务的不一样TCP状态的链接数量的统计: ~]# netstat -nalt | awk '/^tcp\>/{state[$NF]++}END{for(stat in state){printf "%15s: %-10d\n",stat,state[stat]}}' ESTABLISHED: 1 LISTEN: 12 用于统计本服务器web站点的每一个用户的请求数值: ~]# awk '{ipaddr[$1]++}END{for(ip in ipaddr){print ip,ipaddr[ip]}}' /var/log/httpd/access_log 用于统计本服务器web站点的UV值: ~]# awk '{ipaddr[$1]++}END{for(ip in ipaddr){print ip,ipaddr[ip]}}' /var/log/httpd/access_log | wc -l 9.函数: 内建函数: 数值函数:Numeric Functions rand():返回一个介于0到1之间的随机数; sqrt():对于指定的数值进行开二次方; 字符串函数:String Functions length():计算给定字符串的长度; gsub(r, s [, t]):以r表示的模式来查找t表示的字符串中可以被匹配的内容,并将全部出现的内容替换成s表示的内容; split(s, a [, r [, seps] ]):以seps做为分隔符,利用r表示的模式进行匹配,将s表明的字符串分割以后,保存在a表示的数组中; 自定义函数: function name(parameter list) { statements }