Linux Awk用法总结.doc

上传人:sccc 文档编号:4842439 上传时间:2023-05-18 格式:DOC 页数:16 大小:63.50KB
返回 下载 相关 举报
Linux Awk用法总结.doc_第1页
第1页 / 共16页
Linux Awk用法总结.doc_第2页
第2页 / 共16页
Linux Awk用法总结.doc_第3页
第3页 / 共16页
Linux Awk用法总结.doc_第4页
第4页 / 共16页
Linux Awk用法总结.doc_第5页
第5页 / 共16页
点击查看更多>>
资源描述

《Linux Awk用法总结.doc》由会员分享,可在线阅读,更多相关《Linux Awk用法总结.doc(16页珍藏版)》请在三一办公上搜索。

1、Linux Awk用法总结Awk、sed与grep,俗称Linux下的三剑客,它们之间有很多相似点,但是同样也各有各的特色,相似的地方是它们都可以匹配文本,其中sed和awk还可以用于文本编辑,而grep则不具备这个功用。sed是一种非交互式且面向字符流的编辑器(a non-interactive stream-oriented editor),而awk则是一门模式匹配的编程语言,因为它的主要功能是用于匹配文本并处理,同时它有一些编程语言才有的语法,例如函数、分支循环语句、变量等等,当然比起我们常见的编程语言,Awk相对比较简单。使用Awk,我们可以做以下事情:将文本文件视为由字段和记录组成的

2、文本数据库;在操作文本数据库的过程中能够使用变量;能够使用数学运算和字符串操作能够使用常见的编程结构,例如条件分支与循环;能够格式化输出;能够自定义函数;能够在awk脚本中执行UNIX命令;能够处理UNIX命令的输出结果;装备以上功能,awk能够做得事情非常多。但千里之行,始于足下,我们首先从最基本的命令行语法开始,一步一步得走入awk的编程世界。命令行语法同sed一样,awk的命令行语法也有两种形式:awk -F ERE -v assignment . program argument .awk -F ERE -f progfile . -v assignment .argument .这里

3、的program类似sed中的script,因为我们一直强调awk是一门编程语言,所以将awk的脚本视为一段代码。而awk的脚本同样可以写到一个文件中,并通过-f参数指定,这一点和sed是一样的。program一般多个pattern和action序列组成,当读入的记录匹配pattern时,才会执行相应的action命令。这里有一点要注意,在第一种形式中,除去命令行选项外,program参数一定要位于第一个位置。Awk的输入被解析成多个记录(Record),默认情况下,记录的分隔符是n,因此可以认为一行就是一个记录,记录的分隔符可以通过内置变量RS更改。当记录匹配某个pattern时,才会执行后

4、续的action命令。而每个记录由进一步地被分隔成多个字段(Field),默认情况下字段的分隔符是空白符,例如空格、制表符等等,也可以通过-F ERE选项或者内置变量FS更改。在awk中,可以通过$1,$2.来访问对应位置的字段,同时$0存放整个记录,这一点有点类似shell下的命令行位置参数。关于这些内容,我们会在下面详细介绍,这里你只要知道有这些东西就好。标准的awk命令行参数主要由以下三个:-F ERE:定义字段分隔符,该选项的值可以是扩展的正则表达式(ERE);-f progfile:指定awk脚本,可以同时指定多个脚本,它们会按照在命令行中出现的顺序连接在一起;-v assignme

5、nt:定义awk变量,形式同awk中的变量赋值,即name=value,赋值发生在awk处理文本之前;为了便于理解,这里举几个简单的例子。通过-F参数设置冒号:为分隔符,并打印各个字段:kodangodevops $ echo 1:2:3 | awk -F: print $1 and $2 and $31 and 2 and 3在awk的脚本中访问通过-v选项设置的变量:kodangodevops $ echo | awk -v a=1 BEGIN print a1从上面可以看到,通过-v选项设置的变量在BEGIN的位置就可以访问了。BEGIN是一个特殊的pattern,它在awk处理输入之前

6、就会执行,可以认为是一个初始化语句,与此对应的还有END。好像还没介绍如何指定处理的文件,是不是最后的argument就是指定的文件?在看我这本书之前,我也是这样认为的,但是实际上arguemnt有两种形式,它们分别是输入文件(file)和变量赋值(assignment)。awk可以同时指定多个输入文件,如果输入文件的文件名为-,表示从标准输入读取内容。变量赋值类似-v选项,它的形式为name=value。awk中的变量名同一般的编程语言无太多区别,但是不能同awk的保留关键字重名,可以查看awk的man手册查询哪些是保留关键字。而变量值只有两种形式:字符串和数值。变量赋值必须位于脚本参数的后

7、面,与文件名参数无先后顺序的要求,但是位于不同位置的赋值它的执行时机是不同的。我们用实际的例子来解释这个区别,假设有两个文件:a和b,它们的内容分别如下所示:kodangodevops awk_temp$ cat afile akodangodevops awk_temp$ cat bfile b为了说明赋值操作发生的时机,我们在BEGIN,正常处理,END三个地方都打印变量的值。第一种情况: 变量赋值位于所有文件名参数之前kodangodevops awk_temp$ awk BEGIN print BEGIN: var print PROCESS: var END print END: v

8、ar var=1 aBEGIN: PROCESS: 1END: 1结果:赋值操作发生在正常处理之前,BEGIN动作之后。第二种情况:变量赋值位于所有文件名之后:kodangodevops awk_temp$ awk BEGIN print BEGIN: var print PROCESS: var END print END: var a var=1 BEGIN: PROCESS: END: 1结果:赋值操作发生在正常处理之后,END动作之前。第三种情况:变量赋值位于文件名之间:kodangodevops awk_temp$ awk BEGIN print BEGIN: var print P

9、ROCESS: var END print END: var a var=1 bBEGIN: PROCESS: PROCESS: 1END: 1结果:赋值操作发生在处理前面的文件之后,并且位于处理后面的文件之前;总结如下:如果变量赋值在第一个文件参数之前,在BEGIN动作之后执行,影响到正常处理和END动作;如果变量赋值在最后一个文件参数之后,在END动作之前执行,仅影响END动作;如果文件参数不存在,情况同1所述;如果变量赋值位于多个文件参数之间,在变量赋值前面的文件被处理后执行,影响到后续文件的处理和END动作;所以变量赋值一定要考虑清楚用途,否则比较容易出错,不过一般情况下也不会用到变量

10、赋值。自然地大家会将变量赋值与-v assignment选项进行比较,赋值的形式是一致的,但是-v选项的执行时机比变量赋值要早:kodangodevops awk_temp$ echo 1 | awk -v var=a BEGIN print BEGIN: varBEGIN: a可见,-v选项的赋值操作在BEGIN动作之前就执行了。变量赋值一定要小心不要与保留关键字重名,否则会报错:kodangodevops awk_temp$ echo 1 | awk -v BEGIN=1 BEGIN print BEGIN: BEGINawk: fatal: cannot use gawk builtin

11、 BEGIN as variable name记录(Record)与字段(Field)对于数据库来说,一个数据库表是由多条记录组成的,每一行表示一条记录(Record)。每条记录由多列组成,每一列表示一个字段(Field)。Awk将一个文本文件视为一个文本数据库,因此它也有记录和字段的概念。默认情况下,记录的分隔符是回车,字段的分隔符是空白符,所以文本文件的每一行表示一个记录,而每一行中的内容被空白分隔成多个字段。利用字段和记录,awk就可以非常灵活地处理文件的内容。可以通过-F选项来修改默认的字段分隔符,例如/etc/passwd的每一行都是由冒号分隔成多个字段的,所以这里就需要将分隔符设置

12、成冒号:kodangodevops awk_temp$ awk -F: print $1 /etc/passwd | head -3rootbindaemon这里通过$1引用第一人字段,类似地$2表示第二个字段,$3表示第三个字段. $0则表示整个记录。内置变量NF记录着字段的个数,所以$NF表示最后一个字段:kodangodevops awk_temp$ awk -F: print $NF /etc/passwd | head -3/bin/bash/bin/false/bin/false当然,$(NF-1)表示倒数第二个。内置变量FS也可以用于更改字段分隔符,它记录着当前的字段分隔符:ko

13、dangodevops awk_temp$ awk -F: print FS /etc/passwd | head -1:kodangodevops awk_temp$ awk -v FS=: print $1 /etc/passwd | head -1root记录的分隔符可以通过内置变量RS更改:kodangodevops awk_temp$ awk -v RS=: print $0 /etc/passwd | head -1root如果将RS设置成空,行为有就一点怪异了,它会将连续不为空行的所有行(一个段落)当作一个记录,而且强制回车为字段分隔符:kodangodevops awk_tem

14、p$ cat awk_man.txt The awk utility shall execute programs written in the awk programming language,which is specialized for textual data manipulation. An awk program is a sequenceof patterns and corresponding actions. When input is read that matches apattern, the action associated with that pattern i

15、s carried out.Input shall be interpreted as a sequence of records. By default, a record is a line,less its terminating , but this can be changed by using the RS built-invariable. Each record of input shall be matched in turn against each pattern in theprogram. For each pattern matched, the associate

16、d action shall be executed.kodangodevops awk_temp$ awk BEGIN RS=;FS=: print First line: $1 awk_man.txt First line: The awk utility shall execute programs written in the awk programming language,First line: Input shall be interpreted as a sequence of records. By default, a record is a line,这里,我们将变量赋值

17、放到BEGIN动作中执行,因为BEGIN动作是在文件处理之前执行的,专门用于放初始化的语句。FS的赋值在这里是无效的,awk依然使用回车符来分隔字段。脚本(Script)组成命令行中的program部分,可以称为awk代码,也可以称为awk脚本。一段awk脚本是由多个pattern action 序列组成的。action是一个或者多个语句,它在输入行匹配pattern的时候被执行。如果pattern为空,表明这个action会在每一行处理时都会被执行。下面的例子简单地打印文件的每一行,这里不带任何参数的print语句打印的是整个记录,类似print $0:kodangodevops awk_t

18、emp$ echo -e line1nline2 | awk print line1line2除了pattern action ,还可以在脚本中定义自定义的函数,函数定义格式如下所示:function name(parameter list) statements 函数的参数列表用逗号分隔,参数默认是局部变量,无法在函数之外访问,而在函数中定义的变量为全局变量,可以在函数之外访问,如:kodangodevops awk_temp$ echo line1 | awk function t(a) b=a; print a; print b; t(kodango.me); print b;kodan

19、go.mekodango.meAwk脚本中的语句使用空行或者分号分隔,使用分号可以放在同一行,不过有时候会影响可读性,尤其是分支或循环结构中,很容易出错。如果Awk中的一个语句太长,要分成多行,可以在行为使用反斜杠:kodangodevops awk_temp$ cat test.awk function t(a) b=a print This is a very long line, so use backslash to escape the newline then we will print the variable a: a= a print b; t(kodango.me); pr

20、int b;kodangodevops awk_temp$ echo 1 | awk -f test.awk This is a very long line, so use backslash to escape the newline then we will print the variable a: a=kodango.mekodango.me这里我们将脚本写到文件中,并通过-f参数来指定。但是,在一些特殊符号之后,是可以直接换行的,例如, 模式(Pattern)模式是awk中比较重要的一部分,它有以下几种情况:/regular expression/: 扩展的正则表达式(Extend

21、ed Regular Expression), 关于ERE可以参考这篇文章;relational expression: 关系表达式,例如大于、小于、等于,关系表达式结果为true表示匹配;BEGIN: 特殊的模式,在第一个记录处理之前被执行,常用于初始化语句的执行;END: 特殊的模式,在最后一个记录处理之前被执行,常用于输出汇总信息;pattern, pattern:模式对,匹配两者之间的所有记录,类似sed的地址对;例如查找匹配数字3的行:kodangodevops awk_temp$ seq 1 20 | awk /3/ print313相反地,可以在在正则表达式之前加上!表示不匹配:

22、kodangodevops awk_temp$ seq 1 5 | awk !/3/ print1245除了BEGIN和END这两个特殊的模式外,其余的模式都可以使用或者|运算符组合,前者表示逻辑与,后者表示逻辑或:kodangodevops awk_temp$ seq 1 50 | awk /3/ 1331前面的正则都是整行匹配,有时候仅仅需要匹配某个字符,这样我们可以用表达式$n /ere/:kodangodevops $ awk $1 /ko/ print /etc/passwdkodango:x:1000:1000:/home/kodango:/bin/bash有时候我们只想显示特定和

23、行,例如显示第一行:kodangodevops $ seq 1 5 | awk NR=1 print1正则表达式(Regular Expression)和sed篇一样,这里我不会详细介绍正则表达式。因为正则表达式的内容介绍起来太麻烦,还是推荐同学阅读现有的文章(如Linux/Unix工具与正则表达式的POSIX规范),里面对各个流派的正则表达式归纳地很清楚了。表达式(Expressions)表达式可以由常量、变量、运算符和函数组成,常数和变量的值可以为字符串和数值。Awk中的变量有三种类型:用户定义的变量,内置变量和字段变量。其中,内置变量名都是大写的。变量并不非一定要被声明或者被初始化,一个

24、变量默认的值是空字符串,只是在某些上下文上会隐式的自动转换成数字0(例如数学运算),记住awk中的变量是无类型的,不存在字符串变量还是数字变量的区别,只是有时候为了解说方便,才会这么说。(感谢网友紫云妃的提醒)字段变量可以用$n来引用,n的取值范围为0,NF。n可以为一个变量,例如$NF代码最后一个字段,而$(NF-1)表示倒数第二个字段。数组数组是一种特殊的变量,awk中的数组都是关联数组,它的下标都是字符串值(man手册中的原话是:All arrays in AWK are associative, i.e. indexed by string values),即使你使用的下标是一个数字,

25、awk也会将下标隐式转换成字符串。所以容易给人一个误解,数组的下标可以是数字或者字符串。数组的赋值很简单,下面将value赋值给数组下标为index的元素:arrayindex=value可以用for.in.语法遍历数组元素,其中item是数组元素对应的下标:for (item in array)当然也可以在if分支判断中使用in操作符:if (item in array)一个完整的例子如下所示:kodangodevops $ echo 1 2 3 | awk for (i=0;i for (i = 0; i print ARGVi inventory-shipped BBS-listawki

26、nventory-shippedBBS-listARGV的用法不仅限于此,它是可以修改的,可以更改数组元素的值,可以增加数组元素或者删除数组元素。a. 更改ARGV元素的值假设我们有a, b两个文件,它们各有一行内容:file a和file b。现在利用ARGV,我们可以做到偷梁换柱:kodangodevops awk_temp$ awk BEGINARGV1=b print afile b这里要注意ARGV1=b的引号不能缺少,否则ARGV1=b会将变量b的值赋值给ARGV1。当awk处理完一个文件之后,它会从ARGV的下一个元素获取参数,如果是一个文件则继续处理,如果是一个变量赋值则执行赋

27、值操作:kodangodevops awk_temp$ awk BEGINARGV1=var=1 print var a b1为什么这里只打印一次变量值呢?可以回头再看看上一篇中介绍变量赋值的内容。而当下一个元素为空时,则跳过不处理,这样可以避开处理某个文件:kodangodevops awk_temp$ awk BEGINARGV1= print a bfile b上面的例子中a这个文件就被跳过了。而当下一个元素的值为-时,表明从标准输入读取内容:kodangodevops awk_temp$ awk BEGINARGV1=- print a baa # - 这里按下CTRL+D停止输入fi

28、le bb. 删除ARGV元素删除ARGV元素和将元素的值赋值为空的效果是一样的,它们都会跳转对某个参数的处理:kodangodevops awk_temp$ awk BEGINdelete ARGV1 print a bfile b删除数组元素可以用delete语句。c. 增加ARGV元素我第一次看到ARGV变量的时候就在想,能不能利用ARGV变量避免提供命令行参数,就像这样:awk BEGINARGV1=a; print但是事实上这样不行,awk会依然从标准输入中获取内容。下面的方法倒是可以,首先增加ARGC的值,再增加ARGV元素,我到现在也没搞懂这两者的区别:kodangodevops

29、 awk_temp$ awk BEGINARGC+=1;ARGV1=a printfile a2.CONVFMT与OFMTAwk中允许数值到字符串相互转换,其中内置变量CONVFMT定义了awk内部数值到字符串转换的格式,它的默认值为%.6g:kodangodevops awk_temp$ awk BEGIN printf CONVFMT=%s, num=%f, str=%sn, CONVFMT, 12.11, 12.11 CONVFMT=%.6g, num=12.110000, str=12.11通过更改CONVFMT,我们可以定义自己的转换格式:kodangodevops awk_temp

30、$ awk BEGIN CONVFMT=%d; printf CONVFMT=%s, num=%f, str=%sn, CONVFMT, 12.11, 12.11 CONVFMT=%d, num=12.110000, str=12与此对应地还有一个内置变量OFMT,它与CONVFMT的作用是类似的,只不过是影响输出的时候数字转换成字符串的格式:kodangodevops awk_temp$ awk BEGIN OFMT=%d;print 12.11 123.ENVIRONENVIRON是一个存放系统环境变量的关联数组,它的下标是环境变量名称,值是相应环境变量的值。例如:kodangodevop

31、s awk_temp$ awk BEGIN print ENVIRONUSER kodango利用环境变量也可以将值传递给awk:kodangodevops awk_temp$ U=hello awk BEGIN print ENVIRONU hello可以利用for.in循环遍历ENVIRON数组:kodangodevops awk_temp$ awk BEGIN for (env in ENVIRON) printf %s=%sn, env, ENVIRONenv; 4.RLENGTH与RSTARTRLENGTH与RSTART都是与match函数相关的,前者表示匹配的子串长度,后者表示匹配

32、的子串位于目标字符串的起始下标。例如:kodangodevops $ awk BEGIN match(hello,world, /llo/); print RSTART,RLENGTH3 3关于match函数,我们会在以后介绍。运算符x Name Type of Result Associativity( expr ) Grouping Type of expr N/A$expr Field reference String N/A+ lvalue Pre-increment Numeric N/A- lvalue Pre-decrement Numeric N/Alvalue + Post-

33、increment Numeric N/Alvalue - Post-decrement Numeric N/Aexpr Numeric N/Aexpr * expr Multiplication Numeric Left.以下省略.语句(Statement)到目前为止,用得比较多的语句就是print,其它的还有printf、delete、break、continue、exit、next等等。这些语句与函数不同的是,它们不会使用带括号的参数,并且没有返回值。不过也有意外,比如printf就可以像函数一样的调用:kodangodevops awk_temp$ echo 1 | awk print

34、f(%sn, abc)abcbreak和continue语句,大家应该比较了解,分别用于跳出循环和跳到下一个循环。delete用于删除数组中的某个元素,这个我们在上面介绍ARGV的时候也使用过。exit的用法顾名思义,就是退出awk的处理,然后会执行END部分的内容:kodangodevops awk_temp$ echo $line1nline2 | awk print;exit END print exit. line1exit.next语句类似sed的n命令,它会读取下一条记录,并重新回到脚本的最开始处执行:kodangodevops awk_temp$ echo $line1nline

35、2 | awk print Before next. print $0 next print After next. Before next.line1Before next.line2从上面可以看出next后面的print语句不会执行。print与printf语句是使用最多的,它们将内容输出到标准输出。注意在print语句中,输出的变量之间带不带逗号是有区别的:kodangodevops awk_temp$ echo 1 2 | awk print $1, $21 2kodangodevops awk_temp$ echo 1 2 | awk print $1 $212print输出时,字段

36、之间的分隔符可以由OFS重新定义:kodangodevops awk_temp$ echo 1 2 | awk OFS=;print $1,$21;2除此之外,print的输出还可以重定向到某个文件中或者某个命令:print items output-fileprint items output-fileprint items | command假设有这一样一个文件,第一列是语句名称,第二列是对应的说明:kodangodevops awk_temp$ cat column.txt statement|descriptiondelete|delete item from an arrayexit

37、|exit from the awk processnext|read next input record and process现在我们要将两列的内容分别输出到statement.txt和description.txt两个文件中:kodangodevops awk_temp$ awk -F| print $1 statement.txt; print $2 description.txt column.txt kodangodevops awk_temp$ cat statement.txt statementdeleteexitnextkodangodevops awk_temp$ cat

38、 description.txt descriptiondelete item from an arrayexit from the awk processread next input record and process下面是一个重定向到命令的例子,假设我们要对下面的文件进行排序:kodangodevops awk_temp$ cat num.list 13295可以通过将print的内容重定向到sort -n命令:kodangodevops awk_temp$ awk print | sort -n num.list 12359printf命令的用法与print类似,也可以重定向到文件或

39、者输出,只不过printf比print多了格式化字符串的功能。printf的语法也大多数语言包括bash的printf命令类似,这里就不多介绍了。awk的函数分成数学函数、字符串函数、I/O处理函数以及用户自定义的函数,其中用户自定义的函数我们在上一篇中也有简单的介绍,下面我们一一来介绍这几类函数。数学函数awk中支持以下数学函数:atan2(y,x):反正切函数;cos(x):余弦函数;sin(x):正弦函数;exp(x):以自然对数e为底指数函数;log(x):计算以e 为底的对数值;sqrt(x):绝对值函数;int(x):将数值转换成整数;rand():返回0到1的一个随机数值,不包含

40、1;srand(expr):设置随机种子,一般与rand函数配合使用,如果参数为空,默认使用当前时间为种子;例如,我们使用rand()函数生成一个随机数值:kodangodevops awk_temp$ awk BEGIN print rand(),rand();0.237788 0.291066kodangodevops awk_temp$ awk BEGIN print rand(),rand();0.237788 0.291066但是你会发现,每次awk执行都会生成同样的随机数,但是在一次执行过程中产生的随机数又是不同的。因为每次awk执行都使用了同样的种子,所以我们可以用srand()

41、函数来设置种子:kodangodevops awk_temp$ awk BEGIN srand();print rand(),rand();0.171625 0.00692412kodangodevops awk_temp$ awk BEGIN srand();print rand(),rand();0.43269 0.782984这样每次生成的随机数就不一样了。利用rand()函数我们也可以生成1到n的整数:kodangodevops awk_temp$ awk function randint(n) return int(n*rand(); BEGIN srand(); print ran

42、dint(10); 3字符串函数awk中包含大多数常见的字符串操作函数。1.sub(ere, repl, in)描述:简单地说,就是将in中匹配ere的部分替换成repl,返回值是替换的次数。如果in参数省略,默认使用$0。替换的动作会直接修改变量的值。下面是一个简单的替换的例子:kodangodevops $ echo hello, world | awk print sub(/ello/, i); print1hi, world在repl参数中kodangodevops $ awk BEGIN var=kodango; sub(/kodango/, hello, print varhell

43、o, kodango2.gsub(ere, repl, in)描述:同sub()函数功能类似,只不过是gsub()是全局替换,即替换所有匹配的内容。3.index(s, t)描述:返回字符串t在s中出现的位置,注意这里位置是从1开始计算的,如果没有找到则返回0。例如:kodangodevops $ awk BEGIN print index(kodango, o)2kodangodevops $ awk BEGIN print index(kodango, w)04.length(s)描述:返回字符串的长度,如果参数s没有指定,则默认使用$0作为参数。例如:kodangodevops $ aw

44、k BEGIN print length(kodango);0kodangodevops $ echo first line | awk print length();105.match(s, ere)描述: 返回字符串s匹配ere的起始位置,如果不匹配则返回0。该函数会定义RSTART和RLENGTH两个内置变量。RSTART与返回值相同,RLENGTH记录匹配子串的长度,如果不匹配则为-1。例如:kodangodevops $ awk BEGIN print match(kodango, /dango/);printf Matched at: %d, Matched substr length: %dn, RSTART, RLENGTH;3Matched at: 3, Matched substr length: 56.split(s, a, fs)描述:将字符串按照分隔符fs,分隔成多个部分,并存到数组a中。注意,存放的位置是从第1个数组元素开始的。如果fs为空,则默认使用FS分隔。函数返回值分隔的个数。例如:kodangodevops $ awk BEGIN split(1;2;3;4;5, arr, ;) for (i in arr) printf arr%d=%dn, i, arri; arr4=4arr5=5arr1=1arr2=2arr3=3这里有一个奇怪的地方

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 建筑/施工/环境 > 农业报告


备案号:宁ICP备20000045号-2

经营许可证:宁B2-20210002

宁公网安备 64010402000987号