awk-实践

实际中遇到的问题

  1. 字符串截取函数 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);
    }
  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'
    }

     

  3. NR和FNR,首先,若是读取一个文件的话,他们是一样的,若是读取多个文件,NR是这几个文件行数的总和,但FNR则在每次读取新的文件时都会从1开始.
  4. 使用awk 将文件中的时间戳转化为日期,可以使用system调用date
    1 echo 1444440491|awk '{system("date -d @\""$0"\" \"+%F %T\"")}'
    2 2015-10-10 09:28:11

  5. 打印指定的字段到最后(使用循环)
    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

     

  6. 打印出在指定范围内不存在的行(使用数组)
     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 }
  7. 指定多个分隔符时,最好不要偷懒,需要写成 -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

 

posted @ 2016-06-17 18:15  zhaoyingnan911  阅读(1318)  评论(0编辑  收藏  举报