awk结构和替换研究

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
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

  • sed与awk实例 文本间隔 在每一行后面增加一空行 将原来的所有空行删除并在每一行后面增加一空行。这样在输出的文...
    stuha阅读 2,004评论 0 20
  • awk: grep,sed,awk grep:文本过滤 sed:文本编辑 awk:文本格式化工具; 1 什么是aw...
    木林森阅读 1,888评论 0 16
  • 知识点 sort uniq cut wc sed命令 awk命令 crontab定时器 sort sort 命令对...
  • 文本处理工具sed sed处理文本时是以行为单位的,每处理完一行就立即打印出来,然后再处理下一行,直至全文处理结束...
    485b1aca799e阅读 2,995评论 0 4
  • 基础命令 主要的命令和快捷键 Linux系统命令由三部分组成:cmd + [options]+[operation...
    485b1aca799e阅读 1,190评论 0 0

友情链接更多精彩内容