awk-实践
实际中遇到的问题
- 字符串截取函数 substr
#!/usr/bin/awk #author:zhaoyingnan #filename:substr.awk #substr 函数 #echo 20150627185312|awk -f substr.awk { #格式化时间格式 #索引1开始 print substr($0,1,4)"-"substr($0,5,2)"-"substr($0,7,2)" "substr($0,9,2)":"substr($0,11,2)":"substr($0,13,2); printf "%04d-%02d-%02d %02d:%02d:%02d\n",substr($0,1,4),substr($0,5,2),substr($0,7,2),substr($0,9,2),substr($0,11,2),substr($0,13,2); }
- 替换函数 sub 和 gsub
#!/usr/bin/awk -f #author:zhaoyingnan #filename:sub.awk #sub 替换函数 #2016-06-27 15:33:51 current_query => [SELECT * FROM `zhs_user_timeline_147` WHERE 1 and `id`>=294037031 limit 1000] BEGIN{ FS="[ `>]"; } { #删除` $0 == sub(/`/, "", $0); print $0; #sub只会替换模式匹配到的第一个匹配 #相当于vi里面的 %s/apple/banana/ #相当于sed 's/apple/banana/' } #!/usr/bin/awk -f #author:zhaoyingnan #filename:gsub.awk #gsub 替换函数 #2016-06-27 15:33:51 current_query => [SELECT * FROM `zhs_user_timeline_147` WHERE 1 and `id`>=294037031 limit 1000] BEGIN{ FS="[ `>]"; } { #删除` $0 == gsub(/`/, "", $0); print $0; #sub会替换模式匹配到的所有的匹配 #相当于vi里面的 %s/apple/banana/g #相当于sed 's/apple/banana/g' }
- NR和FNR,首先,若是读取一个文件的话,他们是一样的,若是读取多个文件,NR是这几个文件行数的总和,但FNR则在每次读取新的文件时都会从1开始.
- 使用awk 将文件中的时间戳转化为日期,可以使用system调用date
1 echo 1444440491|awk '{system("date -d @\""$0"\" \"+%F %T\"")}' 2 2015-10-10 09:28:11
- 打印指定的字段到最后(使用循环)
ps -ef |grep '/usr/local/php/bin/php excute.php' --color|awk '{ if(NF>=15){ for(i=10;i<=NF;i++){ if(NF==i){ printf "%s\n",$i; }else{ printf "%s ",$i; } } } }'|awk '{ for(i=1;i<=NF;i++){ print $i; } }'|sort -n -t _ -k 5|wc -l
- 打印出在指定范围内不存在的行(使用数组)
1 #!/bin/awk -f 2 #author:zhaoyingnan 3 BEGIN{ 4 for(i=0;i<=499;i++) 5 { 6 num[i]=i; 7 } 8 } 9 { 10 exists[$0]=$0; 11 } 12 END{ 13 for(j in num) 14 { 15 if(num[j] in exists) 16 { 17 } 18 else 19 { 20 print "db_community=>zhs_user_timeline_"num[j]" is end"; 21 } 22 } 23 }
- 指定多个分隔符时,最好不要偷懒,需要写成 -F "[.......]"
1 #!/bin/bash 2 #批量修改文件 3 #oldsix-11.html -> linux-11.HTML 4 for file in `ls` 5 do 6 mv $file `echo $file|awk -F "[-.]" '{printf "%s%s%s","linux-",$2,"."toupper($3)}'` 7 done
下面不用看
1 #!/usr/bin/awk -f 2 # 在系统提示下输入脚本 3 # 本文为awk笔记 4 # 5 # ******************************************************************************************************************************************** 6 # awk 命令格式 7 # awk [options] 'pattern{action}' [var1=value1 var2=value2] files 8 # 模式部分和操作部分都是可选的.如果没有指定模式,则操作会应用到全部的记录[zyn1];如果没有指定操作部分,则会输出匹配的全部记录.[zyn2] 9 # 模式部分和操作部分都是可以出现多次. 10 # 11 # ******************************************************************************************************************************************** 12 # 13 # options 选项部分 14 # -f 从脚本中读取awk命令 15 # -F 指定多个字段分割符[zyn3] 16 # -v 赋值一个用户定义变量[zyn4] 17 # 18 # ******************************************************************************************************************************************** 19 # 20 # pattern 模式部分 21 # 由某种表达式组成的语句,模式不能被括在{}内: 22 # BEGIN{} 指定在第一条输入记录被处理之前发生的动作; 23 # END{} 指定在最后一条输入记录之后发生的动作; 24 # 判别条件真伪的表达式:~表示匹配,!~表示不匹配;字符串或数字比较;关系运算;[zyn5] 25 # /模式1/,/模式2/ 指定一个行的范围.[zyn6] 26 # 27 # ******************************************************************************************************************************************** 28 # 29 # action 操作部分 30 # 由{}括起的一条或多条语句组成,语句间用;或者换行符分割,默认操作是打印所有表达式结果为真的文本行: 31 # 格式化输出; 32 # 变量或数组操作; 33 # 内置函数; 34 # 控制流命令 35 # 36 # ******************************************************************************************************************************************** 37 # 38 # 脚本文件格式 39 # 如果同一行上有多个语句或操作,必须用;隔开;如果每条语句都在不同的行上,可以不用加; 40 # 如果操作跟在某个模式后面,它的{就必须与该模式在同一行[zyn2],[zyn5],[zyn6],[zyn7] 41 # 注释要一#开头 42 # 43 # ******************************************************************************************************************************************** 44 # 45 # 正则表达式元字符 46 # ^在串首匹配 $在串尾匹配 .匹配任意单个字符 *匹配零个或多个前一个字符 47 # +匹配一个或多个前一个字符 ?匹配零个或一个前一个字符 []匹配指定字符串组 48 # [^]匹配任意一个不在指定字符串组 |匹配两者之一 ()+匹配一个或多个组合 49 # &用在代替字符串中,代表查找串中匹配到的内容[zyn9] 50 # 51 # ******************************************************************************************************************************************** 52 # 53 # 正则表达式POSIX字符类 54 # [:alnum:]文字数字字符 [:alpha:]文字字符 [:digit:]数字字符 [:graph:]非空字符(包括空格) 55 # [:punct:]标点符号 [:lower:]小写字符 [:upper:]大写字符 [:cntrl:]控制字符 56 # [:space:]所有空白字符(空格,新行,制表符) [:xdigit:]十六进制数字 [:blank:]空格和制表符 57 # 58 # ******************************************************************************************************************************************** 59 # 60 # 关系运算符:<,<=,>,>=,==,!= 61 # ~,!~在正则中的匹配,不匹配 62 # 条件表达式:?:三元运算符,if else 63 # 逻辑运算符:||,&&,! 64 # 算数运算符:+,-,*,/,%,^(求冥),&(求余),++(一元加),--(一元减),赋值=,+=,-=,*=,/=,%=,^=,**= 65 # 范围:/../,/../ 66 # 67 # ******************************************************************************************************************************************** 68 # 69 # 影响流程控制的语句 70 # 除了if,while,for,do之外,还有break,continue,next 71 # 在一个循环中的两个影响流程控制的break以及continue:break是退出循环,continue是终止当前的循环,并开始下一次的循环; 72 # next:可以连续从文件读取内容,忽略脚本的其他操作直到文件被读完[zyn10],[zyn11] 73 # exit:exit使主输入循环退出控制,执行END{}中的操作,如果没有END{},或者换行符分割是在END{}中应用了exit,则终止脚本执行. 74 # 75 # ******************************************************************************************************************************************** 76 # getline函数,注意它不用加上() 77 # getline函数用于从输入中读取下一行,它不仅能读取正常的数据流,而且能处理来自文件和管道的输入[zyn12][zyn13] 78 # getline函数可能的返回值为:1 如果能够读取一行.0 如果到了文件末尾.-1 如果遇到错误 79 # getline函数读取新的行之后,会将其赋值给$0,并且将其分解成字段,同时设置了系统变量NF和NR以及FNR,如若不想改变$0,可将其赋值给别的变量,但是系统变量还是会被设置的 80 # close()函数用于关闭打开的文件和管道 81 # 在不同的系统中,能打开的管道的数量是不同的,但是是都有一定数量的限制的; 82 # 关闭一个管道使得你可以运行同一个命令两次;[zyn13] 83 # 关闭一个输出管道是必要的[zyn14] 84 # ******************************************************************************************************************************************** 85 # 86 # 87 # [zyn1] 88 # awk -f awk.awk lianxi.txt 89 #BEGIN{printf "%s\n","没有模式部分";} 90 #{ 91 # print $0; 92 #} 93 #END{} 94 # 95 # 96 # [zyn2] 97 #BEGIN{printf "%s\n","没有操作部分";} 98 #$0~/^$/{ 99 # print $0; 100 #} 101 #END{} 102 # 103 # 104 # [zyn3] 105 # echo '1,2,3,4,5,6'|awk -f awk.awk 106 #BEGIN{FS=",";OFS="-";} 107 #{ 108 # print $1,$2,$3,$4,$5; 109 #} 110 #END{} 111 # 112 # 113 # [zyn4] 114 # -v awk -vname=$USER -f awk.awk rizhi.txt 使用的是系统变量 115 # awk -vname="haha" -f awk.awk rizhi.txt 自定义变量 116 # awk -vname="haha" -vhome="gg" -f a.awk rizhi.txt 多个变量 117 # awk -vname="zhaoyingnan" -vhome="hebei" -f awk.awk lianxi.txt 118 #BEGIN{OFS="-";} 119 #{} 120 #END{printf "name:%s,home:%s",name,home;} 121 # 122 # 123 # [zyn5] 124 # 在每个非空的行的结尾追加字符,且保留源文件的空行 125 # awk -f awk.awk lianxi_5.txt 126 #BEGIN{} 127 #$0~/^$/{ 128 # print $0; 129 #} 130 #$0!~/^$/{ 131 # print $0"<br/>"; 132 #} 133 #END{} 134 # 135 # 136 # [zyn6] 137 #BEGIN{PS="\"";OFS="\T";} 138 #/<h4>/,/<\/h4>/{ 139 # print $0; 140 # print $2; 141 #} 142 #END{} 143 # 144 # 145 # [zyn7] 146 # awk -f awk.awk lianxi6.txt 147 #BEGIN{FS="\t"} 148 #/^[A]/{ 149 # print $0; 150 #} 151 #$2~/^[rR]/{ 152 # print $0; 153 # } 154 #$2~/^[^rR][^2].*/{ 155 # print $0; 156 # } 157 #END{} 158 # 159 # 160 # [zyn8] fail 161 # POSIX字符类 需要开启posix支持 162 # awk --posix -f awk.awk lianxi6.txt 163 #BEGIN{} 164 #$2~/^[rRaAbB][[:digit:]].*/{ 165 # print $0; 166 # } 167 #END{} 168 # 169 # 170 # [zyn9] fail 171 # &使用 172 #BEGIN{} 173 #/^[rR][sS]/{ 174 # print $0; 175 #} 176 #END{} 177 # 178 # 179 # [zyn10] 180 # 将国家名称顺序修改 181 # awk -f awk.awk country.txt 182 #BEGIN{ 183 # printf "%s\t\t%s\t\t%s\t\t\n","英文全称","英文缩写","中文全称"; 184 #} 185 #{ 186 # if(NR%3!=0) 187 # printf "%s\t\t",$0; 188 # else 189 # printf "%s\n",$0; 190 #} 191 #END{} 192 # 193 # 194 # [zyn10] 195 # 世界各中英文对照表 196 # awk -f awk.awk country_format.txt country_yingwen.txt 197 #BEGIN{FS=",";OFS="\t";} 198 #FILENAME=="country_format.txt"{ 199 # split($0,entry,","); 200 # country[entry[1]]=entry[3]; 201 # next 202 ## print entry[1],entry[2],entry[3]; 203 #} 204 #/[A-Z][a-z]+/{ 205 # for(i=1;i<=NF;i++) 206 # { 207 # if($i in country) 208 # { 209 # $i=country[$i]"("$i")"; 210 # } 211 # } 212 # print $1,$2,$3; 213 #} 214 #END{} 215 # 216 # 217 # [zyn11] 218 # 星期月份对照表 219 # awk -f awk.awk week_and_month_mix.txt week_and_month_desc.txt 220 #BEGIN{FS=",";} 221 #FILENAME=="week_and_month_mix.txt"{ 222 ##week_and_month_mix/txt文件的每一行都会执行action的操作 223 # split($0,swap,","); 224 # week[swap[2]]=swap[3]" "swap[1]; 225 # next 226 #} 227 #/[A-Z][a-z]+[.]?/{ 228 ##只有从不同文件输入内容的时候才会执行 229 # for(i=1;i<=NF;i++) 230 # { 231 # if($i in week) 232 # { 233 # $i=$i"("week[$i]")"; 234 # } 235 # } 236 # print $0; 237 #} 238 #END{} 239 # 240 # 241 # [zyn12] 242 # 测试getline执行流程 243 # 244 #BEGIN{} 245 #/^(AB).*/{ 246 # print $0; 247 # while(getline>0) 248 # { 249 # if($0~/^(KL).*/) 250 # { 251 # a=$0; 252 # print a; 253 # } 254 # else 255 # break 256 # } 257 #} 258 #END{} 259 # 260 # 261 # [zyn13] 262 # getline 从管道读入输入 263 #BEGIN{} 264 #{ 265 # "whoami"|getline me; 266 # close("whoami");#这里必须将这个管道关掉,否则下面的不能用哟 267 # "whoami"|getline my; 268 # "pwd"|getline path; 269 # print $0,me,my,path; 270 #} 271 #END{} 272 # 273 # 274 # [zyn14] 275 # close()关闭一个输出管道 276 #BEGIN{filename="sort7.txt"} 277 #{ 278 # print $0|"sort > sort7.txt" 279 #} 280 #filename=="sort7.txt"{ 281 # while((getline < filename)>0) 282 # { 283 # print $0; 284 # } 285 #} 286 #END{} 287 # 288 # 289 # ******************************************************************************************************************************************** 290 # awk中的函数 291 # gsub(pattern,replace,subject) 292 # 在字符串subject用replace替换和正则表达式pattern相匹配的所有字符串,返回被替换的个数,若没有提供subject则默认为$0 293 # sub(pattern,replace,subject) 294 # 和gsub相同,不同的是,gsub是所有位置的替换,sub只替换第一个位置哟 295 # awk -f awk.awk 10_zhaoyingnan.log 296 #BEGIN{FS="\"";} 297 #{ 298 # sub(/\//,"_",$16); 299 # gsub(/\//,"_",$16); 300 # gsub(/\.[jJ][pP][Gg]/,".jpg",$16); 301 # print $16 302 #} 303 #END{} 304 # 305 # 306 # index(subject,search) 307 # 返回子串search在subject中的位置,若没有则返回0 308 # substr(subject,starposion,length) 309 # 返回subject中从startposion开启,最大长度为length的子串,若没给出length,则返回从startposion开始到结束的子串 310 # awk -f awk.awk 10_zhaoyingnan.log 311 #BEGIN{FS="\""} 312 #{ 313 # print $16,index($16,"pai"); 314 # print $16,index($16,"suipai"); 315 # print $16,substr($16,index($16,"c180")); 316 #} 317 #END{} 318 # 319 # 320 # tolower(subject)将字符串subject中所有的大写字符转换为小写,返回新的字符串 321 # toupper(subject)将字符串subject中所有的小写字符转换为大写,返回新的字符串 322 # awk -f awk.awk 10_zhaoyingnan.log 323 #BEGIN{FS="\""} 324 #{ 325 # print $16,tolower($16),toupper($16); 326 #} 327 #END{} 328 # 329 # 330 # length(subject) 返回subject的长度,若没有指定subject,则返回$0的长度 331 # 332 #BEGIN{FS="\""} 333 #{ 334 # print length,length($16),"中文长度"length("中文"); 335 #} 336 # 337 # 338 # match(subject,pattern) 339 # 如果正则表达式pattern在subject中出现,则返回出现的启始位置,并设置RSTART为该位置,设置RLENGTH为匹配字符串的字符数,否则返回0,并设置RSTART为0,RLENGTH为-1; 340 # echo "APPLE,PALNE"|awk -f awk.awk 341 #BEGIN{FS=","} 342 #{ 343 # for(i=1;i<=NF;i++) 344 # print $i,match($i,/[A-Z]+/),RSTART,RLENGTH; 345 #} 346 #END{} 347 # 348 # 349 # split(subject,array,decollator) 350 # 使用分隔符decollator将subject分解到array数组中,返回元素的个数,如没有给出decollator则使用FS 351 #BEGIN{FS=","} 352 #{ 353 # split($0,array) 354 # for(i in array) 355 # print array[i] 356 #} 357 #END{}
测试用到的文件 sed -n '/^#\s*awk.*\.[tl]/p' awk.awk |uniq # awk -f awk.awk lianxi.txt # awk -vname="haha" -f awk.awk rizhi.txt 自定义变量 # awk -vname="haha" -vhome="gg" -f a.awk rizhi.txt 多个变量 # awk -vname="zhaoyingnan" -vhome="hebei" -f awk.awk lianxi.txt # awk -f awk.awk lianxi_5.txt # awk -f awk.awk lianxi6.txt # awk --posix -f awk.awk lianxi6.txt # awk -f awk.awk country.txt # awk -f awk.awk country_format.txt country_yingwen.txt # awk -f awk.awk week_and_month_mix.txt week_and_month_desc.txt # awk -f awk.awk 10_zhaoyingnan.log