美文网首页
awk结构和替换研究

awk结构和替换研究

作者: 六十三63 | 来源:发表于2018-03-25 00:07 被阅读0次

    awk方面对于初学者来说最难的是结构问题,看不懂结构,那就要面对大量的语法syntax报错(我的感觉)

    首先一个例子

    [vagrant@amainst perltest]$ ls -lt
    total 64
    -rw-rw-r--. 1 vagrant vagrant   292 Mar 24 13:51 testfile
    -rw-rw-r--. 1 vagrant vagrant 48894 Mar 21 11:11 testfile.bak
    -rwxrwxrwx. 1 vagrant vagrant   332 Mar 20 15:13 fzonefile
    -rw-rw-r--. 1 vagrant vagrant   204 Mar 20 14:37 result
    -rw-rw-r--. 1 vagrant vagrant    66 Mar 15 15:47 test.pl
    

    对于以上数据,我要第3行的other的权限是多少,我怎么弄出来呢?
    管道组合是最快的

    #加个tail -n +2从第二行开始输出
    [vagrant@amainst perltest]$ ls -lt|tail -n +2
    -rw-rw-r--. 1 vagrant vagrant   292 Mar 24 13:51 testfile
    -rw-rw-r--. 1 vagrant vagrant 48894 Mar 21 11:11 testfile.bak
    -rwxrwxrwx. 1 vagrant vagrant   332 Mar 20 15:13 fzonefile
    -rw-rw-r--. 1 vagrant vagrant   204 Mar 20 14:37 result
    -rw-rw-r--. 1 vagrant vagrant    66 Mar 15 15:47 test.pl
    #加个sed -n '3'p打印第三行
    [vagrant@amainst perltest]$ ls -lt|tail -n +2|sed -n '3'p
    -rwxrwxrwx. 1 vagrant vagrant   332 Mar 20 15:13 fzonefile
    #加个awk '{print $1}'显示第一域(我不说列,在awk里对于有分隔符的数据,统称域field,不称列column)
    [vagrant@amainst perltest]$ ls -lt|tail -n +2|sed -n '3'p|awk '{print $1}'
    -rwxrwxrwx.
    #加个cut -c 8-10截取8-10位的字符
    [vagrant@amainst perltest]$ ls -lt|tail -n +2|sed -n '3'p|awk '{print $1}'|cut -c 8-10
    rwx
    

    但如果用awk来呢

    [vagrant@amainst perltest]$ ls -lt|awk 'NR==4{split($1,a,"");for(i=8;i<=10;i++){if(i==10){printf("%s\n",a[i])}else{printf("%s",a[i])}}}'
    rwx
    

    是不是感觉天书了
    分行来分析一下结构

    [vagrant@amainst perltest]$ ls -lt|awk 'NR==4{split($1,a,"")#首先是awk的pattern里进行了一个判断NR==4,这里我写在了外面,匹配的是第四行。然后第四行的第一域用split分割成数组a,分隔符是空,就是按字符分隔split($1,a,""),要注意的是awk里数组的下标默认是从1开始。
    > for(i=8;i<=10;i++)#由于awk里没有a[8-10]这种数组截取的写法,这里写了个循环
    > {if(i==10){printf("%s\n",a[i])}#在循环里判断是否是数组10,如果是10,就需要输出的时候带上回车符
    > else{printf("%s",a[i])}
    > }
    > }'
    rwx
    

    拆掉每个分支的声明。结果如下

    awk '{if(判断式){
                    干啥{
                         这里有个循环{
                                     这里还有个if分支(判断式){
                                                           真的情况
                                                          }else{
                                                          假的情况}    
                                    }
                        }
                     }
         }'
    

    这样就可以更容易理解其结构

    接下来就说awk的替换了,我之前一直很少用awk的替换原因之一就是还不懂awk的结构,替换的道理用的却是sed的思维,即sed 's/pattern1/pattern2/'。

    弄清楚awk的结构以后替换就更容易理解一点。以下,我替换fzonefile为chmyfile。用sed和awk对比

    [vagrant@amainst perltest]$ ls -lt|sed 's/fzonefile/chmyfile/'
    total 64
    -rw-rw-r--. 1 vagrant vagrant   292 Mar 24 13:51 testfile
    -rw-rw-r--. 1 vagrant vagrant 48894 Mar 21 11:11 testfile.bak
    -rwxrwxrwx. 1 vagrant vagrant   332 Mar 20 15:13 chmyfile
    -rw-rw-r--. 1 vagrant vagrant   204 Mar 20 14:37 result
    -rw-rw-r--. 1 vagrant vagrant    66 Mar 15 15:47 test.pl
    [vagrant@amainst perltest]$ ls -lt|awk '{if($NF=="fzonefile"){sub("fzonefile","chmyfile",$NF)};print}'
    total 64
    -rw-rw-r--. 1 vagrant vagrant   292 Mar 24 13:51 testfile
    -rw-rw-r--. 1 vagrant vagrant 48894 Mar 21 11:11 testfile.bak
    -rwxrwxrwx. 1 vagrant vagrant 332 Mar 20 15:13 chmyfile
    -rw-rw-r--. 1 vagrant vagrant   204 Mar 20 14:37 result
    -rw-rw-r--. 1 vagrant vagrant    66 Mar 15 15:47 test.pl
    

    分析awk这个结构

    [vagrant@amainst perltest]$ ls -lt|awk '{if($NF=="fzonefile"){sub("fzonefile","chmyfile",$NF)}#当最后一域为fzonefile的时候,用sub方法替换fzonefile为chmyfile
    > print}'#打印出全部内容,这个不在前一行的if分支里
    total 64
    -rw-rw-r--. 1 vagrant vagrant   292 Mar 24 13:51 testfile
    -rw-rw-r--. 1 vagrant vagrant 48894 Mar 21 11:11 testfile.bak
    -rwxrwxrwx. 1 vagrant vagrant 332 Mar 20 15:13 chmyfile
    -rw-rw-r--. 1 vagrant vagrant   204 Mar 20 14:37 result
    -rw-rw-r--. 1 vagrant vagrant    66 Mar 15 15:47 test.pl
    

    有什么作用,因为我以前一直有个误区,用以下命令举例

    [vagrant@amainst perltest]$ ls -lt|awk '/fzonefile/{sub("fzonefile","chmyfile",$NF);print}'
    -rwxrwxrwx. 1 vagrant vagrant 332 Mar 20 15:13 chmyfile
    

    为什么只显示了一行的结果呢?
    因为你的awk ’/pattern/‘里就只有一个if判断(用/关键字匹配/),所以print显示的结果自然只有一行,这就没了sed的功能。

    那以上那么多废话以后,我怎么不傻瓜化的就用sed去完成我所有的替换需求呢?
    因为sed的内判断循环问题一时还没掌握,先用awk来试试看。
    例如,替换文本中test为new,但是不替换带bak的字符串

    [vagrant@amainst perltest]$ ls -lt |awk '{if($NF~/test/&&$NF!~/bak/){sub("test","new",$NF)};print}'
    total 64
    -rw-rw-r--. 1 vagrant vagrant 292 Mar 24 13:51 newfile
    -rw-rw-r--. 1 vagrant vagrant 48894 Mar 21 11:11 testfile.bak
    -rwxrwxrwx. 1 vagrant vagrant   332 Mar 20 15:13 fzonefile
    -rw-rw-r--. 1 vagrant vagrant   204 Mar 20 14:37 result
    -rw-rw-r--. 1 vagrant vagrant 66 Mar 15 15:47 new.pl
    

    相关文章

      网友评论

          本文标题:awk结构和替换研究

          本文链接:https://www.haomeiwen.com/subject/mryccftx.html