awk介绍
AWK是一种优良的文本处理工具。它不仅是 Linux 中也是任何环境中现有的功能最强大的数据处理引擎之一。这种编程及数据操作语言(其名称得自于它的创始人 Alfred Aho 、Peter Weinberger 和 Brian Kernighan 姓氏的首个字母)的最大功能取决于一个人所拥有的知识。 AWK 提供了极其强大的功能:可以进行样式装入、流控制、数学运算符、进程控制语句甚至于内置的变量和函数。它具备了一个完整的语言所应具有的几乎所有精美特性。实际上 AWK 的确拥有自己的语言:AWK 程序设计语言, 三位创建者已将它正式定义为“样式扫描和处理语言”。它允许您创建简短的程序,这些程序读取输入文件、为数据排序、处理数据、对输入执行计算以及生成报表,还有无数其他的功能。 免费的awk版本 贝尔实验室的awk gawk mawk awka
awk调用方式
1.命令行方式 awk 'commands' file.txt #file.txt是待处理的文件 2.shell脚本方式 #! /bin/awk #..... 3.将所有awk命令插入一个单独的文件 awk -f awk-script-file file.txt #awk-script-file中包含了awk执行的脚本,file.txt是待处理的文件
表达式,变量
#字符串 echo "" | awk '{a="aa" "bb"; print a}' #结果 aabb echo "" | awk '{a="aabb"; print a}' #结果 aabb echo "" | awk '{a="123"; n=a+1; print n}' #结果 124 echo "" | awk '{n=0.03125; print n}' echo "" | awk '{n=3.125e-2; print n}' echo "" | awk '{n=0.003125E1; print n}' #结果 0.03125
数值运算符优先级
= += -= *= /= %= ^= **= | 赋值 |
?: | C条件表达式 |
|| | 逻辑或 |
&& | 逻辑与 |
~ ~! | 匹配正则表达式和不匹配正则表达式 |
< <= > >= != == | 关系运算符 |
空格 | 连接 |
+ - | 加,减 |
* / & | 乘,除与求余 |
+ - ! | 一元加,减和逻辑非 |
^ *** | 求幂 |
++ -- | 增加或减少,作为前缀或后缀 |
$ | 字段引用 |
in | 数组成员 |
指数操作
awk 'BEGIN{ print 2^10}' awk 'BEGIN{ print 2**10}'
内建变量
$n | 当前记录的第n个字段,字段间由FS分隔。 |
$0 | 完整的输入记录。 |
ARGC | 命令行参数的数目。 |
ARGIND | 命令行中当前文件的位置(从0开始算)。 |
ARGV | 包含命令行参数的数组。 |
CONVFMT | 数字转换格式(默认值为%.6g) |
ENVIRON | 环境变量关联数组。 |
ERRNO | 最后一个系统错误的描述。 |
FIELDWIDTHS | 字段宽度列表(用空格键分隔)。 |
FILENAME | 当前文件名。 |
FNR | 同NR,但相对于当前文件。 |
FS | 字段分隔符(默认是任何空格)。 |
IGNORECASE | 如果为真,则进行忽略大小写的匹配。 |
NF | 当前记录中的字段数。 |
NR | 当前记录数。 |
OFMT | 数字的输出格式(默认值是%.6g)。 |
OFS | 输出字段分隔符(默认值是一个空格)。 |
ORS | 输出记录分隔符(默认值是一个换行符)。 |
RLENGTH | 由match函数所匹配的字符串的长度。 |
RS | 记录分隔符(默认是一个换行符)。 |
RSTART | 由match函数所匹配的字符串的第一个位置。 |
SUBSEP | 数组下标分隔符(默认值是\034) |
内建变量操作
#FNR相当于文件行号 for i in {a..j}; do echo $i; done | awk '{print FNR}' #每行的字段个数 for i in {a..j}; do echo $i; done | awk '{print NF}' #已经读出的记录数,就是行号(不是输入文件的行号) for i in {a..j}; do echo $i; done | awk '{print NR}' #修改输出字段分隔符 echo "aa bb cc dd" | awk 'BEGIN{OFS="@"} {print $1,$2,$3}' #修改输入记录的分隔符(默认是\n) echo "aa-bb-cc-dd-ee" | awk 'BEGIN{RS="-"} {print $1}' #修改输出记录的分隔符(默认是\n) cat hehe.txt | awk 'BEGIN{ORS="@"} {print $1} END{print "\n"}' #将每行打印到一个特定的文件中,这个文件名就是字段六(比如TIME_WAIT,LISTEN) netstat -anpt | awk 'NR!=1{print > $6}'
数组变量
telephone["Alice"] = "555-0134" telephone["Bob"] = "555-0135" telephone["Carol"] = "555-0136" telephone["Don"] = "555-0141" 这种数组称为关联数组,可以定义 x[1] = 3.14 x[10000] = "test" 之间不需要填满2-99999个元素,所以这些存储空间是稀疏的 del x[1] #删除数组x中的元素 del x #删除数组x 的所有元素 echo "" | awk '{a["test"]=100; a["hehe"]=123; a[100]=99; for(i in a){print i,a[i]} }' #结果,i是key,a[i]是value 100 99 test 100 hehe 123
环境变量
#内建变量 ENVIRON(注意大写小)可以获取所有系统环境变量,也就是env命令中的所有值 echo "" | awk '{print "hostname=" ENVIRON["HOSTNAME"]; print "shell=" ENVIRON["SHELL"]; print "user=" ENVIRON["USER"]; }' #结果 hostname=test-vm shell=/bin/bash user=root #可以获得自定义的系统变量 export aaa=hehe echo "" | awk '{print ENVIRON["aaa"]}'
命令行参数
#使用ARGC获得传入的命令参数长度 #使用ARGV获得向量数组,获取参数值 awk 'BEGIN{print "ARGC=" ARGC; for(j=0;j<ARGC;j++){print "ARGV[" j "]=[" ARGV[j] "]" } }' hehe.txt aa=bb ?? a1=1 #结果 ARGC=5 ARGV[0]=[awk] ARGV[1]=[hehe.txt] ARGV[2]=[aa=bb] ARGV[3]=[??] ARGV[4]=[a1=11]
字段和分隔符
#默认是空格分隔 echo "aa bb cc dd" | awk '{print $1 " - " $2}' #指定一个特定的分隔符 #$1就是第一个字段。$2是第二个字段,以此类推 echo "aa@bb@cc@dd" | awk -F "@" '{print $1 " - " $2}' #还可以写成 echo "aa@bb@cc@dd" | awk 'BEGIN{FS="@"} {print $1 " - " $2}' #分隔符可以有多个字符组成,这点比cut强 echo "aa=@#=bb=@#=cc=@#=dd" | awk -F "=@#=" '{print $1 " - " $2}'
模式与操作
awk程序的操作模式如下
命令 | 含义 |
pattern {action} | 如模式匹配,则执行操作 |
pattern | 如模式匹配,则打印记录 |
{action} | 针对每条记录,执行操作 |
#匹配一个模式,执行操作 echo "aa bb cc dd" | awk '/aa/ {print $3}' #可以匹配多个模式,/pattern/ && /pattern/ 这种形式 for i in {a..j}; do echo $i; done | awk '/c/ || /d/ || /e/ || !/[f-z]/ {print $1}' #使用 $1 ~ /pattern/ 这种形式可以针对某个特定字段进行匹配,同样可以匹配 #多个字段或者多个模式 for i in {a..j}; do echo $i; done | awk '$1 ~ /c/ || $1 ~/d/ || $1 !~/[e-z]/ {print $0}' #使用if匹配 for i in {a..j}; do echo $i; done | awk '{if($1=="c"){print "ok!"} }' #BEGIN:让用户指定在第一条输入记录被处理之前所发生的动作,通常可在 #这里设置全局变量。 for i in {a..j}; do echo $i; done | awk 'BEGIN{print "BEGIN"}' #END:让用户在最后一条输入记录被读取之后发生的动作。 for i in {a..j}; do echo $i; done | awk 'END{print "END!"}' #范围匹配,匹配第一个c的行和第一个f行,并打印这些行 for i in {a..j}; do echo $i; done | awk '/c/, /f/{ print "-->"$1}'
选择和循环
#放到awk_test.sh中 #if和else if多重判断 echo "" | awk '{ srand(); num = rand() * 10; if(num < 3) { print "num < 3" } else if(num > 3 && num < 5) { print "num>3 && num<5" } else if(num < 9) { print "num < 9" } else { print "unknow..." } }' #while循环 echo "" | awk '{i=1; while(i<5){print i; i++}}' #do while echo "" | awk '{ i=1; do{print i; i++;}while(i<5) }' #for循环 echo "" | awk '{ for(i=0;i<5;i++){print i} }' #for each循环 #求出netstat的状态,获取10行,然后记录到关联数组中,最后遍历关联数组并打印 netstat | head | awk '{print $6}' | sed '/^$/d' | awk '{sum[$1]++} END{ for(s in sum){print s ","sum[$1]} }'
用户控制的输入
getline的各种用法
命令 | 含义 |
getline | 从当前输入文件中,读取下一条记录,存入$0,并更新NF,NR和FNR |
getline var | 从当前输入文件中,读取下一条记录,存入var,并更新NR和FNR |
getline < file | 从file中读取下一条记录,存入$0,并更新var |
getline var < file | 从file中读取下一条记录,存入var |
cmd | getline | 从外部命令cmd读取下一条记录,存入$0,并更新NF |
cmd | getline var | 从外部命令cmd读取下一条记录,存入var |
用户输入和外部命令
#getline读取下一行 awk '/^1/ && /1$/ {getline; print $0}' hehe.txt ' #读取命令行的结果 echo "" | awk '{"date" | getline var ; print var}' #这里的命令行结果有多行,但是echo "" 只有一行,所以awk的{} #语句只执行一次 #这样只能读取ls -l 中的第一行了,如果要读取ls -l的全部结果,需要保证 #echo "" 这样的语句返回的行数和ls -l的行数一样才可以 echo "" | awk '{"ls -l" | getline var; print var}' #想要全部读取可以使用这种方式 echo "" | awk '{command="head -n 10 /etc/passwd"; while((command | getline s) > 0){print s;} }' #通过system()函数调用外部命令,此时可以返回全部结果 echo "" | awk '{system("ls -l")}' #重定向输出 awk '{print $0 > "/data0/test/test.log"}' hehe.txt #next,当碰到netx会忽略掉next之后的所有语句然后读取下一行继续执行 seq 10 | awk '{ if($1==3){next;} print $0 }'
数学函数
函数名 | 含义 |
atan2( y, x ) | 返回 y/x 的反正切 |
cos( x ) | 返回 x 的余弦;x 是弧度 |
sin( x ) | 返回 x 的正弦;x 是弧度 |
exp( x ) | 返回 x 幂函数 |
log( x ) | 返回 x 的自然对数 |
sqrt( x ) | 返回 x 平方根 |
int( x ) | 返回 x 的截断至整数的值 |
rand( ) | 返回任意数字 n,其中 0 <= n < 1 |
srand( [Expr] ) |
将 rand 函数的种子值设置为 Expr 参数的值, 或如果省略 Expr 参数则使用某天的时间。返回先前的种子值 |
演示
echo "" | awk '{print atan2(10,2)}' echo "" | awk '{print cos(10)}' echo "" | awk '{print exp(10)}' echo "" | awk '{print int("11@@111111111??11111ss")}' #结果11 echo "" | awk '{print log(10)}' echo "" | awk '{x=rand(); print x}' echo "" | awk '{print sin(90)}' echo "" | awk '{print sqrt(100)}'
时间函数
函数名 | 含义 |
mktime( YYYY MM DD HH MM SS[ DST]) | 生成时间格式 |
strftime([format [, timestamp]]) | 格式化时间输出,将时间戳转为时间字符串 具体格式 |
systime() |
得到时间戳,返回从1970年1月1日开始到当前 时间(不计闰年)的整秒数 |
strftime
格式 | 描述 |
%a | 星期几的缩写(Sun) |
%A | 星期几的完整写法(Sunday) |
%b | 月名的缩写(Oct) |
%B | 月名的完整写法(October) |
%c | 本地日期和时间 |
%d | 十进制日期 |
%D | 日期 08/20/99 |
%e | 日期,如果只有一位会补上一个空格 |
%H | 用十进制表示24小时格式的小时 |
%I | 用十进制表示12小时格式的小时 |
%j | 从1月1日起一年中的第几天 |
%m | 十进制表示的月份 |
%M | 十进制表示的分钟 |
%p | 12小时表示法(AM/PM) |
%S | 十进制表示的秒 |
%U | 十进制表示的一年中的第几个星期(星期天作为一个星期的开始) |
%w | 十进制表示的星期几(星期天是0) |
%W | 十进制表示的一年中的第几个星期(星期一作为一个星期的开始) |
%x | 重新设置本地日期(08/20/99) |
%X | 重新设置本地时间(12:00:00) |
%y | 两位数字表示的年(99) |
%Y | 四位表示的年 |
%Z | 时区(PDT) |
%% | 百分号(%) |
演示
#当前时间戳 echo "" | awk '{print systime()}' #格式化当前时间,strftime是c的函数,可以参考man strftime echo "" | awk '{x=systime(); print strftime("%Y-%m(%B)-%d %H:%M:%S %A",x);}' #mktime,c里面也有这个函数,可以参考man mktime
字符串函数
函数 | 含义 |
gsub( Ere, Repl, [ In ] ) | 除了正则表达式所有具体值被替代这点,它和 sub 函数完全一样地执行 |
sub( Ere, Repl, [ In ] ) |
用 Repl 参数指定的字符串替换 In 参数指定的字符串中的由 Ere 参数指定的扩展正则表达式的第一个 |
index( String1, String2 ) |
在由 String1 参数指定的字符串(其中有出现 String2 指定的参数)中, 返回位置,从 1 开始编号 |
length [(String)] | 返回 String 参数指定的字符串的长度(字符形式) |
substr( String, M, [ N ] ) |
返回具有 N 参数指定的字符数量子串。子串从 String 参数 指定的字符串取得,其字符以 M 参数指定 |
match( String, Ere ) |
在 String 参数指定的字符串(Ere 参数指定的扩展正则表达式出现在其中) 中返回位置(字符形式) |
split( String, A, [Ere] ) |
将 String 参数指定的参数分割为数组元素 A[1], A[2], . . ., A[n], 并返回 n 变量的值。此分隔可 |
tolower( String ) |
返回 String 参数指定的字符串,字符串中每个大写字符将更改为小写。 大写和小写的映射由当前语言环境的 |
toupper( String ) |
返回 String 参数指定的字符串,字符串中每个小写字符将更改为大写。 大写和小写的映射由当前语言环境的 |
sprintf(Format, Expr, Expr, . . . ) |
根据 Format 参数指定的 printf 子例程格式字符串来格式化 Expr 参数指定的表达式并返回 |
printf
格式化 | 含义 |
%d | 十进制有符号整数 |
%u | 十进制无符号整数 |
%f | 浮点数 |
%s | 字符串 |
%c | 单个字符 |
%p | 指针的值 |
%e | 指数形式的浮点数 |
%x | %X 无符号以十六进制表示的整数 |
%o | 无符号以八进制表示的整数 |
%g | 自动选择合适的表示法 |
演示
#替换第一个出现的aa echo "" | awk '{x="aa aa bb cc aa aa xx "; sub("aa","AA",x); print x}' #结果 AA aa bb cc aa aa xx #替换所有的aa echo "" | awk '{x="aa aa bb cc aa aa xx "; gsub("aa","AA",x); print x}' #结果 AA AA bb cc AA AA xx echo "" | awk '{print index("x~!#@# aa bb cc xxx aa ss","aa")}' #结果 8 echo "" | awk '{print index("aa bb cc xxx aa ss","aa")}' #结果 1 echo "" | awk '{print length("abcdefghij")}' echo "" | awk '{print tolower("sdfsdfAAsdf%%SsdfFJGJ")}' echo "" | awk '{print toupper("sdfsdfAAsdf%%SsdfFJGJ")}' echo "" | awk '{print match("hehe999^%^>>???hehe","[0-9]")? "ok~" : "not found"}' echo "" | awk '{a="1234567890aaaaaabbbb"; print substr(a,3,5);}' #结果 34567 echo "" | awk '{x="aa@bb@cc@dd"; split(x,y,"@"); for(i in y){print i"-"y[i]} }' #结果 4-dd 1-aa 2-bb 3-cc #格式化字符串 echo "" | awk '{printf("%s--%d--%f\n","aaaa",111,3.14)}'
自定义函数
其他函数
位操作函数
国际化函数
#欧几里得算法 #执行方式 echo "" | awk -f gcg.awk #! /bin/awk function gcd(x, y) { x = int(x); y = int(y); print x, y r = x % y; return (r==0) ? y : gcd(y,r); } { g = gcd($1, $2); print "gcd(" $1 "," $2 ")=" g; }
#打印5行随机数 for k in {1..5}; do awk 'BEGIN{ srand(); for(k=1;k<=5;k++){printf("%.5f\t",rand());}print }' sleep 1; done
#反向查找函数 #执行方式 echo "" | awk -f rindex.awk #! /bin/awk function rindex(string, find, k, ns, nf) { ns = length(string); nf = length(find); for(k=ns+1-nf; k>=1; k--) { if(substr(string, k, nf) == find) { return k; } } return 0; } { x = rindex("afsdfsdffffffx", "f",1,2,3); print x }
#把数组中的字符串合在一起 执行方式 echo "" | awk -f join.awk #! /bin/awk function join(array) { n = length(array); if(n >= 1) { s = array[1]; for(k=2;k<=n;k++) { s = s "-" array[k]; } } return s; } { a[1] = "aaa"; a[2] = "bbb"; a[3] = "ccc"; a[4] = "ddd"; a[5] = "eee"; print join(a); }
参考
awk man介绍和man strftime介绍
相关推荐
awk总结(分工合作角度)
总结而言,grep、sed和awk这三种工具各有所长,能应对不同复杂度的文本处理需求。grep适用于简单的搜索和计数任务,sed则更加强大,可以进行文本替换和复杂编辑,而awk则类似于一种简化的编程语言,其在文本处理上...
### Shell Awk脚本知识点总结 #### 一、Shell与Awk在文本处理中的应用 在日常工作中,尤其是在技术支持领域,经常会遇到需要处理文本文件的情况。无论是哪种类型的数据库,最终都可以将其导出为文本格式,这为我们...
awk是Linux/Unix环境下强大的文本分析工具,常用于处理结构化的数据文件,如CSV、TSV格式或由制表符分隔的文件。它通过模式匹配和动作来处理输入的数据,使得在shell脚本中进行数据提取、转换和报告生成变得简单。在...
### AWK 文件处理总结 #### 一、AWK 入门篇 AWK 是一种强大的文本处理工具,常用于Linux/Unix环境下。它允许用户通过简单的脚本语言来进行复杂的文本处理任务。 **基本命令格式**: ```bash awk 'pattern { action...
通过上述总结,我们可以看出awk是一个功能极其强大的文本处理工具,它不仅可以用于简单的文本搜索和替换,还能进行复杂的数据分析和报告生成。掌握awk的基本用法和高级技巧,对于提高工作效率和数据处理能力具有重要...
### 总结 AWK是一种专门为文本处理和数据分析而设计的编程语言。它适合于快速编写简短但功能强大的程序来完成特定任务。AWK的语法简洁,提供了丰富的内置函数和灵活的数据处理能力,使得它成为数据处理领域中的一个...
`END`规则在处理完所有输入后执行,通常用于总结和打印统计信息。 **8. 处理多个文件** `awk`可以同时处理多个文件,如`awk 'ACTION' file1 file2 ...`。当处理多个文件时,`FNR`会跟踪每个文件的行数。 **9. ...
#### 五、总结 Awk 是一种强大的文本处理工具,尤其适用于 Unix/Linux 环境下的文本模式扫描和数据处理任务。通过灵活运用不同的调用方式,可以极大地提高工作效率,解决各种文本处理需求。无论是简单的命令行应用...
根据您提供的文件内容,这里总结了关于awk的一些知识点。 ### 1. Awk概述 Awk是一种编程语言,用于处理文本模式和报告生成。它主要用于Linux操作系统,并广泛应用于UNIX Shell编程中。Awk按照记录和字段的方式来...
#### 七、总结 AWK作为一款功能强大的文本处理工具,在Linux和Unix环境中有着广泛的应用。无论是简单的文本处理还是复杂的数据分析,AWK都能够提供高效的解决方案。通过本文的学习,希望能够帮助读者更好地理解和...
### 总结 awk是一种极其灵活且功能强大的文本处理工具,在Linux/Unix系统中具有广泛的应用。掌握awk的基本语法和高级特性对于提高文本处理效率和实现自动化任务至关重要。无论是简单的模式匹配还是复杂的逻辑处理,...
Linux中的`awk`是一个强大的文本分析工具...总结,`awk`是Linux文本处理的重要工具,其灵活性和强大的功能使其在数据分析、日志分析等领域有着广泛的应用。通过深入学习和实践,我们可以充分利用`awk`来提高工作效率。
总结: 在本文中,我们比较了shell和awk两个工具在大数据处理中的速度差异。awk的速度远远高于shell,主要是因为awk是一种功能强大且灵活的文本处理语言,具有高效的处理能力。选择合适的工具是非常重要的。在大...
根据给定文件的信息,我们可以总结出以下关于 AWK 应用和讲解步骤的相关知识点: ### 一、AWK 基础语法 AWK 是一个强大的文本处理工具,在 Linux 和 Unix 系统中广泛使用。AWK 的基本命令格式如下: ``` awk [选项...