awk

一颗蔬菜 2019-07-05 PM 257℃ 1条
学习背景

昨天被老哥安排了一个微小的work,我知道,用shell来处理1分钟可以搞定,当然我只是知道可以这么做,最后我用了15分钟完成了这个微小的work。

学习之前:Ctrl+C && Ctrl+V 耗时:15mins 。

学习之后:awk '$3 != null { print $3 > "new.txt" }' 耗时:1mins。

awk简介

awk在江湖中被coders称为“Linux Shell 编程四剑客”,它经常被当作强大的Shell命令被使用,而它本质上是一种强大的程序设计语言。本文从Shell命令的视角对awk进行简单学习,想要系统地了解awk的同学们可以参考awk官方文档

入门

先从简单的案例看起,假设有名为demo.txt的文件,其内容:

silver  1  1980  Liberty doller
gold  1  1980  USA  Liber dollar
silver  2  1909  CH  Panda
gold  0.7  1567  Liberty doller
silver  2  1909  CH  Panda
gold  1  1908  ingot
silver  2  1909  CH  Panda
gold  0.7  1567  Liberty doller
gold  1  1980  USA  Liber dollar
silver  2  1909  CH  Panda
gold  0.7  1567  Liberty doller
gold  1  1908  ingot
silver  2  1909  CH  Panda
silver 2  1656  Panda
gold  1  1980  USA  Liber dollar
silver  2  1909  CH  Panda
silver  2  1909  CH  Panda
gold  0.7  1567  Liberty doller

1.查看该文件的全部内容:

awk '{ print }' demo.txt
awk '{ print $0 }' demo.txt

2.查看第2列内容:

awk '{ print $2 }' demo.txt

3.查看第一列和第二列内容:

awk '{ print $1, $2 }' # awk检测到逗号时,会将第一列和第二列以空格分开。

awk默认把空格作为拼接符,因此awk '{ print $1 $2 }' demo.txt 的输出结果是两列连接在一起。

4.查看第二列和第三列内容,并以#作为分隔符:

awk '{ print $2 "#" $3 }' demo.txt

运行结果:
以#作为分隔符.png
通过以上几行微小的命令,可以大概了解awk可以干什么,接下来学习稍微高级一点的用法。

内建变量的使用

维基百科:

awk的内建变量包括域变量,例如$1, $2, $3,以及$0。这些变量给出了记录中域的内容。 内建变量也包括一些其他变量:

  • NR:已输入记录的条数。
  • NF:当前记录中域的个数。记录中最后一个域可以以$NF的方式引用。
  • FILENAME:当前输入文件的文件名。
  • FS:“域分隔符”,用于将输入记录分割成域。其默认值为“空白字符”,即空格和制表符。FS可以替换为其它字符,从而改变域分隔符。
  • RS:当前的“记录分隔符”。默认状态下,输入的每行都被作为一个记录,因此默认记录分隔符是换行符
  • OFS:“输出域分隔符”,即分隔print命令的参数的符号。其默认值为空格。
  • ORS:“输出记录分隔符”,即每个print命令之间的符号。其默认值为换行符。
  • OFMT:“输出数字格式”(Format for numeric output),其默认值为"%.6g"。

接下来介绍一些常用的用法:

1.在awk中,将文本内容划分为若干行和若干列,一行就是一条记录,即Record,每一行的行号用NR来表示;同理,每一列的即一个Field,列号用NF表示。

查看demo.txt的全部内容,并显示行号和每一行的列数:

awk '{ print NR, $0, NF }' demo.txt

运行结果:

带NR和NF的执行结果.png

2.awk支持带条件查询。

(1)查看第7行的全部内容

awk 'NR == 7 { print }' demo.txt 

运行结果:
查看第7行的全部内容.png

同理,也可以使用awk 'NF == 5 { print }' demo.txt 命令查看列数为5的行的全部内容。

(2)查看第三列年份为1909的行的所有内容。

awk '$3 == 1909 { print $0 }' demo.txt 

运行结果:

查看第三列为1909的行的全部内容.png

3.awk不但能从文本文件中查找内容,也能从命令行读取参数

awk '{ print $1 $2 }'

运行结果:

从命令行读取参数.png

4.awk支持输入分隔符FS和输出分隔符OFSFS默认为空格和制表符,OFS默认为空格

awk 'BEGIN{ FS = ","; OFS="@" } { print $1, $2 }'

运行结果:
输入分隔符和输出分隔符的使用.png

5.awk支持一次查看多个文件,并显示每一行记录所属的文件的文件名

awk '{ print NR, FILENAME ,$0 }' demo.txt data.txt # 

运行结果:
查看多个文件.png

6.awk支持临时为某一行或某一列赋值,当我们需要为客户展示一个表格的数据,同时又不想让客户看到其中的一列数据,可以这么做:

awk '{ $3 = "此项保密"; print NR, $0 }' demo.txt

运行结果:
临时赋值.png

当然这么做,并不会真正地改变第三列数据,只是在查看该文档时将该项临时赋值为“此项保密”。

7.awk支持查看倒数第n列

awk '{ print $NF, $(NF - 1) }' demo.txt
自定义变量和运算

awk支持自定义变量和运算。

1.加法

awk '{ a = 1;b = 2;c = 3;print a + b c }'
awk '{ a = 1;b = 2;c = 3;print (a + b) c }'

以上两行命令的运行结果是一致的:33。这两行命令完成的工作是先将a和b相加,然后将相加的结果和c拼接。

awk '{ a = 1;b = 2;c = 3;print a + b, c }'

以上这条命令的运行结果是3 3。注意两个3之间是有空格的,逗号是分隔符。

2.减法

awk '{ a = 1;b = 2;c = 3;print a - c b }'

3.乘法

awk '{ a = 1;b = 2;print a * b }'

4.除法

awk '{ a = 1;b = 3;print a / b }'

5.取余

awk '{ a = 4;b = 2;print a % b }'

6.awk能自动识别变量的数据类型,而不需要开发者定义:

awk '{ a = "hello";b = 3;c = 4;print a + b +c }'
awk '{ a = "hello";b = 3;c = 4;print a b +c }'

运行结果:
自动识别变量类型.png

awk还支持许多变量类型和内置函数、流程控制以及格式化输出,详情可前往官方文档

模式

1.BEGIN { 语句 }

在读取任何输入前执行一次语句

2.END { 语句 }

在读取所有输入后执行一次语句

3.表达式 { 语句 }

若表达式为真(包括非空、非零),则执行 语句

4.组合模式 { 语句 }

通过 &&、||等来组合多个表达式。若组合模式为真(包括非空、非零),则执行语句

5.模式1,模式2 { 语句 }

范围模式,匹配从与模式1相匹配的行到与模式2相匹配的行之间的行,对于这些行,执行语句

6.正则表达式 { 语句 }

如果输入行与正则表达式相匹配,则执行语句

注意:BEGIN和END不与其他模式组合。范围模式不可以是任何其他模式的一部分。BEGIN和END是仅有的必须搭配动作的模式。

结束语

学习是不断迭代的过程。

标签: shell

非特殊说明,本博所有文章均为博主原创。



唉呀 ~ 仅有一条评论


  1. heart4lor
    heart4lor

    还有sed,grep,也都是我不会用的神器

    回复 2019-07-18 21:14