关于shell:awk 的学习

正所谓,知己知彼百战不殆,想要拿下awk,必需了解它的前世今生;

一、它可以做什么

    1、 awk 是一种编程语言, 可以用作linux或者Unix的bash脚本中;也可以单独放在一个文件中,通过awk命令解释器运行;

          【这里只关注awk用作bash脚本中】

    2、awk 主要功能是,基于指定的规则,对文本或者数据做浏览和提取操作;  其处理原则为:逐行扫描文件,从第一行到最后一行,寻找匹配指定规则的内容。   【awk命令的主要功能是对文本做提取操作,所以,bash脚本编写中,awk经常与其它指令联合是使用:通过awk提取指定行,然后对该行做你所需要的操作。

二、它怎么使用呢 

   1、语法结构

      awk    选项部分    '命令部分'    文件名

            1)选项部分:为一些指定的参数,或者正则表达式;

            2)命令部分:为需要运行的操作和指令,一般是用『 '{}' 』包围起来,用来表示执行的所有操作;

            3)文件名: 就是我们要处理的文件;

        【基本的awk 指令语法构成就是如上所示,也有一些更高阶的操作,这个后续再学习】

 2、一些基本概念 【写在前面的东西】

    1)分隔符和域   

        分隔符,就是语法结构中的『选项』部分,  awk指令中,通过 -F   来定义字段的分隔符; awk指令默认的分隔符为空格,如果要处理的文件时以空格分割,则无需指定选项 -F ;  如果是通过除空格之外的其它字符分割,则必需指定-F ;

        域: 定义了分隔符,则比如会有文本被分割成一段一段的, 这里统称为域; 域的标记符为:$1,  $2,  $3 ...  $n  ;  其中,$0 表示所有的域;   一个栗子:

一、定义文件【文件包含多列,列之间通过逗号分割】:
vim 1
序号,姓名,年龄,职业$
1,张三,19,学生$
2,李四,25,程序员$
3,王五,40,教师$


 执行: awk -F ,  '{print $0}'  1

输出结果为:
序号,姓名,年龄,职业
1,张三,19,学生
2,李四,25,程序员
3,王五,40,教师

   执行:awk -F ,  '{print $1}'   1
输出结果为:
序号
1
2
3

【解析】:  -F  定义分隔符为逗号; 如果是以其它字符分割,则直接更换即可;
   $0  定义域,这里输出全部域;  【可以通过域标识符,更换输出的域, 比如$1, 则只输出第一列】 
   1   为我定义的文件名字;

      【备注】若是以其他分隔符做为分割,则直接替换 参数-F 的取值即可;如下:

定义文件【文件包含多列,以\t分割】
vim  3
序号^I姓名^I年龄^I职业^I去年工资^I今年工资$     
1^I张三^I19^I学生^I1200^I1000$  
2^I李四^I25^I程序员^I10000^I15000$
3^I王五^I40^I教师^I5000^I6000$

执行:awk -F \t '{print $2}' 3

输出结果为:
姓名
张三
李四
王五


【解析】:  此处,文件以\t分割,则对应-F 参数值改为\t,  则可以正确提取;
          同理,可以以\n 分割;

    2)模式和动作

         模式和动作,位于语法结构中的『命令部分』, 故需要使用 '{ }'   包含起来;         

     他们说,awk语句,是由『模式』和『动作』两部分组成的;那么什么是模式,什么是动作呢?

     动作:就是,定义对数据的具体操作;【也就是一些列的操作指令】;

     模式:则定义了『动作』被触发的条件; 

               【可以是条件语句、正则匹配、复合语句等】;

               【当然了,这并非必需的,若没有定义模式,则动作将保持时刻被触发的状态】

               【模式以关键词BEGIN和END来标识, 其中BEGIN 定义在 动作之前执行;  END定义的内容则在动作之后执行】

        一个栗子:

还是文件: 1;

执行如下指令:
$ awk -F , 'BEGIN {print "---start print the file---"} {print $2} END {print "---the end---"}'  1 


输出结果为:
---start print the file---
姓名
张三
李四
王五
---the end---



#解析:  
1、-F: 定义分隔符,不做解释;
2、'BEGIN {print "---start print the file---"} {print $2} END {print "---the end---"}'   为模式定义和动作定义;  单引号不能省略;
  1)其中  BEGIN {print "---start print the file---"}   定义动作开始前执行的操作; 
  2){print $2}  为动作定义;
  3) END {print "---the end---"}'  定义动作结束后执行的操作;
  4)每一个操作,需要{};
  

三、一些常用到的操作符 和  内置变量、内置函数;

    1、定义了一个文件 1 ,文件中包含内容为:

    

    2、定义文件nihao,文件中包含内容为:

      

   1、 awk指令中可以使用的操作符:     

操作符

操作指令  【指令部分,需要用双引号表示字符串】作用
<  、<=  、 > 、 >=

awk -F , '{if ($5 < $6) print   $2 "工资涨了"}'    1

输出:

    李四工资涨了

     王五工资涨了

比较文件中,第6列和第5列数值大小,满足要求,则输出;
==  、 != 

 awk -F ,  '{if ($2=="李四") print $2 "在表中"}'  1

 输出:

     李四在表中

用于精确匹配; 和 精确不匹配
/[Pp]/

 awk '/[pP]/'  nihao 

输出:

      前两行,因为前两行中包含了P 或者p

用来匹配大小写,
~   『匹配正则表达式』待补充 
!~ 『不匹配正则表达式』待补充 

 2、awk 指令的内置变量

   1)NF

     [作用及其应用场景]:

           A、awk按行读取文本, NF标识每一行的字段数【即列数】;【 直接输出'{print NF}',    则可以输出该行的列数;】

           B、$NF 标识,该行的最后一列; 处理文本时,可能每一行列数不同,获取最后一列时,可以使用该方法;

           C、这里的字段数,是根据指定分隔符分割后的字段数

      [举个栗子]:         

文件内容:
序号,姓名,年龄,职业,去年工资,今年工资
1,张三,19,学生,1200,1000
2,李四,25,程序员,10000,15000
3,王五,40,教师,5000,6000

执行1:awk -F ,  '{print NF}' 1
结果为:【输出每一行的列数】
6
6
6
6

执行2:awk -F ,  '{print $NF}' 1
结果为:【输出最后一列】
今年工资
1000
15000
6000

   2)NR

     [作用及其应用场景]:

          A、AWK 按行读取文本,  NR 标识每一行的行号;  

          B、可以根据行号,实现对应的筛选;

     【举个栗子】:

文件内容:
序号,姓名,年龄,职业,去年工资,今年工资
1,张三,19,学生,1200,1000
2,李四,25,程序员,10000,15000
3,王五,40,教师,5000,6000

执行1:awk '{print NR}' 1
结果为:
1
2
3
4

执行2: awk '{if (NR>3)  print "输出行号大于3的记录:" $0}'  1
结果为:输出行号大于3的记录:3,王五,40,教师,5000,6000

      3)FNR

       [作用及其应用场景]:

            A、FNR 也标识 文本的行号; 

            B、同NR的区别在于:

                     读取多个文件时, NR会将多个文件的行号都依次连起来,顺序获取;  

                     FNR,则可以识别不同的文件开端, 每读到一个新的文件,行号从1开始; 

        【举个栗子】

文件a.txt
a,aa,aaa,1
b,bb,bbb,2
c,cc,ccc,3
d,dd,ddd,4
e,ee,eee,5

文件b.txt
a,aa,aaa,1
b,bb,bbb,2
c,cc,ccc
a,dd,ddd,4
e,ee,eee,5

执行1:awk '{print "NR:" NR "FNR:" FNR}' a.txt  b.txt
结果为:
   NR:1FNR:1
   NR:2FNR:2
   NR:3FNR:3
   NR:4FNR:4
   NR:5FNR:5
   NR:6FNR:1
   NR:7FNR:2
   NR:8FNR:3
   NR:9FNR:4
   NR:10FNR:5

执行2:
awk -F ,'{if(NR==FNR){arry[NR]=$0} else{if(arry[FNR]!=$0){print FNR}}}' a.txt b.txt
结果为:
3
4

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值