1、awk 命令详解 (转 整理)一、前言awk 有 3 个不同版本: awk、nawk 和 gawk,未作特别说明,一般指 gawk。awk 语言的最基本功能是在文件或字符串中基于指定规则来分解抽取信息,也可以基于指定的规则来输出数据。完整的 awk 脚本通常用来格式化文本文件中的信息。二、基本语法awk opion awk_script input_file1 input_file2 .awk 的常用选项 option 有: -F fs : 使用 fs 作为输入记录的字段分隔符,如果省略该选项,awk 使用环境变量 IFS 的值 -f filename : 从文件 filename 中读取 a
2、wk_script -v var=value : 为 awk_script 设置变量awk 有三种运行方式:第一种,把 awk 的脚本命令直接放在命令中。第二种,把 awk 的所有的脚本命令放在一个脚本文件中,然后用 -f 选项来指定要运行的脚本命令文件。第三种,将 awk_script 放入脚本文件并以 #!/bin/awk -f 作为首行,给予该脚本可执行权限,然后在 shell 下通过键入该脚本的脚本名调用之。三、awk 脚本awk 脚本可以由一条或多条 awk_cmd 组成,对于多个 awk_cmd,一个 awk_cmd 完成后,应该另起一行,以便进行隔。 awk_cmd 由两部分组成
3、: awk_pattern actions 。另外,在 awk 命令中直接使用 awk_script 时,awk_script 也可以被分成多行书写,但必须确保整个 awk_script 被单引号括起来。awk 命令的一般形式:awk BEGIN actions awk_pattern1 actions awk_patternN actions END actions inputfile其中 BEGIN actions 和 END actions 是可选的。在 awk 脚本中可以使用 AWK 本身内置变量,如下: ARGC 命令行变元个数ARGV 命令行变元数组FILENAME 当前输入文件名
4、FNR 当前文件中的记录号FS 输入域分隔符,默认为一个空格RS 输入记录分隔符NF 当前记录里域个数NR 到目前为止记录数OFS 输出域分隔符ORS 输出记录分隔符awk 脚本的运行过程: 如果 BEGIN 区块存在, awk 执行它指定的 actions。 awk 从输入文件中读取一行,称为一条输入记录。( 如果输入文件省略,将从标准输入读取) awk 将读入的记录分割成字段,将第 1 个字段放入变量 $1 中,第 2 个字段放入$2,以此类推。$0 表示整条记录。字段分隔符使用 shell 环境变量 IFS 或由参数指定。 把当前输入记录依次与每一个 awk_cmd 中 awk_patt
5、ern 比较,看是否匹配,如果相匹配,就执行对应的 actions。如果不匹配,就跳过对应的 actions,直到比较完所有的 awk_cmd。 当一条输入记录比较了所有的 awk_cmd 后,awk 读取输入的下一行,继续重复步骤和,这个过程一直持续,直到 awk 读取到文件尾。 当 awk 读完所有的输入行后,如果存在 END,就执行相应的 actions。1)input_file 可以是多于一个文件的文件列表,awk 将按顺序处理列表中的每个文件。2)一条 awk_cmd 的 awk_pattern 可以省略,省略时不对输入记录进行匹配比较就执行相应的 actions。一条 awk_cm
6、d 的 actions 也可以省略,省略时默认的动作为打印当前输入记录 ,即print $0 。一条 awk_cmd 中的 awk_pattern 和 actions 不能同时省略。3) BEGIN 区块和 END 区块别位于 awk_script 的开头和结尾。awk_script 中只有 END 区块或者只有 BEGIN 区块是被允许的。如果 awk_script 中只有 BEGIN actions ,awk 不会读取 input_file。4) awk 把输入文件的数据读入内存,然后操作内存中的输入数据副本,awk 不会修改输入文件的内容。5) awk 的总是输出到标准输出,如果想让 a
7、wk 输出到文件,可以使用重定向。3.1.awk_patternawk_pattern 模式部分决定 actions 动作部分何时触发及触发 actions。awk_pattern 可以是以下几种类型:1) 正则表达式用作 awk_pattern: /regexp/注意,正则表达式 regexp 必须被/ 包起来awk 中正则表达式匹配操作中经常用到的字符: $ . | () * / :通用的 regexp 元字符+ : 匹配其前的单个字符一次以上,是 awk 自有的元字符,不适用于 grep 或 sed 等? : 匹配其前的单个字符 1 次或 0 次,是 awk 自有的元字符,不适用于 gr
8、ep 或 sed 等关于正则表达式的更多内容请参正则表达式举例:awk / *$0.0-90-9.*/ input_file比如,行内容为$0.99. helllo 的行就可以和上面的正则表达式相配2) 布尔表达式用作 awk_pattern,表达式成立时,触发相应的 actions 执行。 表达式中可以使用变量(如字段变量 $1,$2 等) 和/regexp/ 布尔表达式中的操作符:关系操作符: = = !=匹配操作符: value /regexp/ 如果 value 匹配/regexp/ ,则返回真value ! /regexp/ 如果 value 不匹配/regexp/,则返回真举例:
9、awk $2 10 print “ok“ input_fileawk $3 /d/ print “ok“ input_file ENDprint “total points :“ tot input_file / 分号不能省略awk tot+=$6 print $0 ENDprint “total points :“ tot input_file / 与上面等效当使用赋值表达式时,表示如果赋值后的变量是数字的话,如果为非 0,就匹配,否则不匹配;如果为字符串的话,非空就为匹配,否则不匹配。awk 内置字符串函数:gsub(r, s) 在整个$0 中用 s 替代 rawk gsub(/name/
10、,“xingming“) print $0 tempgsub(r, s,t) 在整个 t 中用 s 替代 rindex(s,t) 返回 s 中字符串 t 的第一位置awk BEGIN print index(“Sunny“,“ny“) temp 返回 4length(s) 返回 s 的长度match(s,r) 测试 s 是否包含匹配 r 的字符串awk $1=“J.Lulu“ print match($1,“u“) temp 返回 4split(s, a,fs) 在 fs 上将 s 分成序列 aawk BEGIN print split(“12#345#6789“,myarray,“#“)“返
11、回 3,同时 myarray1=“12“, myarray2=“345“, myarray3=“6789“sprint(fmt,exp) 返回经 fmt 格式化后的 expsub(r, s) 从$0 中最左边最长的子串中用 s 代替 r(只更换第一遇到的匹配字符串)substr(s,p) 返回字符串 s 中从 p 开始的后缀部分substr(s,p,n) 返回字符串 s 中从 p 开始长度为 n 的后缀部分awk 字符串连接操作 chengmocentos5 $ awk BEGINa=“a“;b=“b“;c=(a“b);print c ab 2.7. printf 函数的使用:字符转换: ec
12、ho “65“ |awk printf “%cn“,$0 输出 Aawk BEGIN printf “%fn“,999 输出 999.000000格式化输出:awk printf “%-15s %sn“,$1,$3 temp 将第一个域全部左对齐显示2.8. 其他 awk 用法:向一行 awk 命令传值:awk if ($5who | awk if ($1=user) print $1 “ are in “ $2 user=$LOGNAME 使用环境变量awk 脚本命令:开头使用 !/bin/awk -f ,如果没有这句话自含脚本将不能执行,例子:!/bin/awk -f# all comme
13、nt lines must start with a hash # name: student_tot.awk# to call: student_tot.awk grade.txt# prints total and average of club student points# print a header firstBEGINprint “Student Date Member No. Grade Age Points Max“print “Name Joined Gained Point Available“print“=“# lets add the scores of points
14、 gained(tot+=$6);# finished processing now lets print the total and average pointENDprint “Club student total points :“ totprint “Average Club Student points :“ tot/N2.9. awk 数组:awk 的循环基本结构For (element in array) print arrayelementawk BEGIN record=“123#456#789“;split(record,myarray,“#“) END for (i in
15、 myarray) print myarrayi 3.0 awk 中自定义语句一.条件判断语句(if)if(表达式) #if ( Variable in Array )语句 1else语句 2格式中“语句 1“可以是多个语句,如果你为了方便 Unix awk 判断也方便你自已阅读,你最好将多个语句用括起来。Unix awk 分枝结构允许嵌套,其格式为:if(表达式)语句 1else if(表达式)语句 2else语句 3chengmolocalhost nginx# awk BEGIN test=100;if(test90)print “very good“;else if(test60)pr
16、int “good“;elseprint “no pass“;very good每条命令语句后面可以用“;”号结尾。二.循环语句(while,for,do)1.while 语句格式:while(表达式 )语句例子:chengmolocalhost nginx# awk BEGIN test=100;total=0;while(i0)print $1 data.txtQUOTE:nawk getline d; print d”#”$3 data.txtawk 首先读入第一行,接着处理 getline 函数,然后把下一行指定给变量 d,再先打印 d,由于 d 后面有换行符,所以后面紧跟的会覆盖 d
17、,后面的$3 同样也会覆盖 d。QUOTE:nawk getline; print $0”#”$3 data.txtawk 首先读入第一行接着处理 getline 函数,然后把下一行指定给 $0,现在的$0 已经是下一行内容,后面的#和$3(从$0 中取)会覆盖$0 的内容。在 awk 中,有时需要调用系统工具来完成 awk 不擅长的工作,awk 提供的 system 命令可以用来执行,但收不到外部工具的输出结果。好在可以运用 getline 来满足这个需求。例如test.awk:datecommand=“/bin/date -j -f “%d/%b/%Y:%H:%M:%S“ “ $olddatestr “ “+%Y%m%d %H%M%S“;datecommand | getline newdatestr close(datecommand);外部命令需要 awk 占用一个文件描述符,而 awk 最多能打开的文件有一个上限,而且不大(比如说 16),所以最后做一个 close 是好习惯。把命令串定义为一个变量也是为了 close的时候方便