Linux命令学习:awk命令介绍awk是一个强大的文本分析工具,相对于grep搜索,sed编辑器,awk在分析数据和生成报告时的强大尤为重要。简单来说,awk是逐行读取文件,将每一行以空格作为默认分隔符进行切片,然后对切片的部分进行各种分析处理。awk有3个不同版本:awk、nawk和gawk,不特别说明,一般指gawk,gawk是AWK的GNU版本。awk的名字来源于其创始人AlfredAho、PeterWeinberger和BrianKernighan姓氏的首字母。AWK实际上有自己的语言:AWK编程语言,三位创建者已将其正式定义为“样式扫描和处理语言”。它允许您创建读取输入文件、排序数据、处理数据、对输入执行计算、生成报告和无数其他功能的短程序。使用方法awk'{pattern+action}'{filenames}虽然操作可能很复杂,但语法总是相同的,其中pattern表示AWK在数据中寻找什么,而action是当一个找到匹配顺序。大括号({})不需要在程序中始终如一地出现,但它们用于根据特定模式对指令序列进行分组。pattern是要表达的正则表达式,用斜杠括起来。awk语言最基本的功能是根据指定的规则浏览和提取文件或字符串中的信息。awk提取信息后,就可以进行其他文本操作了。完整的awk脚本通常用于格式化文本文件中的信息。通常,awk在一行中处理一个文件。awk接收文件的每一行,然后执行相应的命令来处理文本。awk调用awk1有3种方式。命令行方法awk[-Ffield-separator]'commands'input-file(s)其中commands是真正的awk命令,[-Ffieldseparator]是可选的。输入文件是要处理的文件。在awk中,文件中的每一行,由字段分隔符分隔的每一项称为一个字段。通常,当不指定-F字段分隔符时,默认的字段分隔符是空格。2.shell脚本方法将所有awk命令插入到一个文件中,并使awk程序可执行,然后将awk命令解释器作为脚本的第一行,通过输入一次脚本名来调用。相当于shell脚本第一行:#!/bin/sh可以换成:#!/bin/awk3。将所有awk命令插入到一个单独的文件中,然后调用:awk-fawk-script-fileinput-file(s)其中-f选项加载awk-script-file中的awk脚本,input-file(s)同上。本章重点介绍命令行方法。入门示例假设last-n5的输出如下[root@www~]#last-n5<==只取出前五行rootpts/1192.168.1.100TueFeb1011:21stillloggedinrootpts/1192.168.1.1002月10日星期二00:46-02:28(01:41)rootpts/1192.168.1.1002月9日星期一11:41-18:30(06:48)dmtsaipts/1192.168。1.100MonFeb911:41-11:41(00:00)roottty1FriSep514:09-14:10(00:01)如果只显示最后5次登录#last-n5|awk'{print$1}'rootrootrootdmtsairootawkworks过程是这样的:读入一条由'n'换行符分隔的记录,然后按照指定的字段分隔符将记录分成字段,并填充字段,$0表示所有字段,$1表示第一个字段,$n表示第n个域的第一个字段。默认域分隔符是“空白键”或“[tab]键”,所以$1表示登录用户,$3表示登录用户ip,以此类推。如果只显示/etc/passwd的账号#cat/etc/passwd|awk-F':''{print$1}'rootdaemonbinsys是awk+action的例子,每次都会执行action{print$1}线。-F指定字段分隔符为':'。如果只显示/etc/passwd的账号和该账号对应的shell,账号和shell用tab键隔开#cat/etc/passwd|awk-F':''{print$1"\t"$7}'root/bin/bashdaemon/bin/shbin/bin/shsys/bin/sh如果只显示/etc/passwd的账号和该账号对应的shell,账号和shell之间用逗号,并将列名名称添加到所有行,shell,将“blue,/bin/nosh”添加到最后一行。cat/etc/passwd|awk-F':''BEGIN{print"name,shell"}{print$1","$7}END{print"blue,/bin/nosh"}'name,shellroot,/bin/bashdaemon、/bin/shbin、/bin/shsys、/bin/sh....blue、/bin/noshawk工作流程是这样的:先执行BEGING,然后读取文件,读取文件以/n行分隔breakA记录,然后按照指定的字段分隔符将记录分成字段,填充字段,$0表示所有字段,$1表示第一个字段,$n表示第n个字段,然后开始执行对应的action图案。然后开始读取第二条记录……直到读取完所有记录,最后执行END操作。在/etc/passwd中搜索具有根关键字的所有行#awk-F:'/root/'/etc/passwdroot:x:0:0:root:/root:/bin/bash这是一个示例pattern的使用,只有匹配到pattern的行(这里是root)才会执行action(如果没有指定action,默认输出每一行的内容)。搜索支持正则表达式,例如查找root开头:awk-F:'/^root/'/etc/passwd搜索/etc/passwd中所有包含root关键字的行,并显示对应的shell#awk-F:'/root/{print$7}'/etc/passwd/bin/bash这里指定action{print$7}awk内置变量awk有很多内置变量用来设置环境信息,这些变量可以被更改,最常用的变量在下面给出。ARGC命令行参数个数ARGV命令行参数排列ENVIRON支持队列中的系统环境变量,使用FILENAMEawk浏览文件名FNR浏览文件的记录数FS设置输入字段分隔符,相当于命令行-F选项NF浏览记录NumberoffieldsNR读取记录数OFS输出字段分隔符ORS输出记录分隔符RS控制记录分隔符另外,$0变量指的是整条记录。$1代表当前行的第一个字段,$2代表当前行的第二个字段,以此类推。统计/etc/passwd:文件名,每行行号,每行列数,对应完整行内容:#awk-F':''{print"filename:"FILENAME",linenumber:"NR",列:“NF”,行内容:“$0}”/etc/passwdfilename:/etc/passwd,行号:1,列:7,行内容:root:x:0:0:root:/root:/bin/bashfilename:/etc/passwd,linenumber:2,columns:7,linecontent:daemon:x:1:1:daemon:/usr/sbin:/bin/shfilename:/etc/passwd,linenumber:3,columns:7,linecontent:bin:x:2:2:bin:/bin:/bin/shfilename:/etc/passwd,linenumber:4,columns:7,linecontent:sys:x:3:3:sys:/dev:/bin/sh使用printf代替print可以使代码更简洁易读awk-F':''{printf("filename:%10s,linenumber:%s,columns:%s,linecontent:%s\n",FILENAME,NR,NF,$0)}'/etc/passwdprint和printfawk提供用于打印输出的print和printf函数。打印函数的参数可以是变量、值或字符串。字符串必须用双引号括起来,参数用逗号分隔。如果没有逗号,参数将被串联起来并且无法区分。在这里,逗号的作用和输出文件的分隔符一样,只不过后者是一个空格。printf函数,它的用法基本类似于C语言中的printf,可以格式化字符串,当输出比较复杂时,printf更易用,代码也更容易理解。awk编程变量和赋值除了awk的内置变量外,awk还可以自定义变量。下面统计/etc/passwd中的账号数awk'{count++;print$0;}END{print"usercountis",count}'/etc/passwdroot:x:0:0:root:/root:/bin/bash......用户数为40count是一个自定义变量。前面的action{}只有一个print,其实print只是一个语句,而action{}可以有多个语句,用;隔开。这里不初始化count,虽然默认是0,但是正确的做法是初始化为0:awk'BEGIN{count=0;print"[start]usercountis",count}{count=count+1;print$0;}END{print"[end]usercountis",count}'/etc/passwd[start]usercountis0root:x:0:0:root:/root:/bin/bash...[end]usercountis40统计文件夹中文件占用的字节数ls-l|awk'BEGIN{size=0;}{size=size+$5;}END{print"[end]sizeis",size}'[end]sizeis8657198如果在M中显示:ls-l|awk'BEGIN{size=0;}{size=size+$5;}END{print"[end]sizeis",size/1024/1024,"M"}'[end]sizeis8.25889M注意统计不包括文件夹的子目录。条件语句awk中的条件语句是从C语言中借用的,见如下语句:if(expression){statement;陈述;......}if(expression){statement;}else{statement2;}if(expression){statement1;}elseif(expression1){statement2;}else{statement3;}统计文件占用的字节数在文件夹中,并过滤大小为4096的文件(通常是文件夹):ls-l|awk'BEGIN{size=0;print"[start]sizeis",size}{if($5!=4096){size=size+$5;}}END{print"[end]sizeis",size/1024/1024,"M"}'[end]sizeis8.22339M循环语句awk中的循环语句也是借鉴了C语言,支持while,do/while,for,break,continue,这些关键字的语义与C语言中的语义完全一致。数组因为awk中数组的下标可以是数字和字母,所以数组的下标通常被称为关键字(key)。值和键在内部存储在对键/值应用散列的表中。由于哈希不是按顺序存储的,当你显示数组的内容时,你会发现它们并没有按照你期望的顺序显示。和变量一样,数组在使用时会自动创建,awk也会自动判断其存储的是数字还是字符串。一般来说,awk中的数组用于从记录中收集信息,可以用来计算总和、统计单词、跟踪模板匹配的次数等。显示/etc/passwd账户awk-F':''BEGIN{count=0;}{name[count]=$1;count++;};END{for(i=0;i
