介绍

awk是一个强大的linux命令,有强大的文本格式化的能力,好比将一些文本数据格式化成专业的excel表的样式。
awk早期在unix上实现,我们用的awk是gawk,是GUN awk的意思。

*我们利用 whic awk 可以查看awk的文件,然后利用 ls -l 查看他的具体信息,我们是可以看到他是一个指向这gawk的软连接

awk更是一门编程语言,支持条件判断、数组、循环等功能。

基础

语法:awk [option] ‘pattern[action]’ file …
awk 参数 ‘条件动作’ 文件/数据

  • action指的是动作,awk擅长文本格式化,且输出格式化后的结果,因此最常用的动作就是 print 和 printf

    场景

  1. 打印文本的第一列

    awk ‘{print $1}’ lianxi.txt

我们执行的命令是 awk ‘{print $2}’ ,没有使用参数和模式,$2 表示输出文本的第二列信息。

  • awk默认以空格为分隔符,且多个空格也识别为一个空格,作为分隔符
  • awk是按行处理文件,一行处理完毕,处理下一行,根据用户指定的分隔符去工作
  • 指定分隔符后,awk把每一行切割后的数据对应到内置变量
  • $0代表整行,1则代表第一列,以此类推
  • $NF表示当前分割后的最后一列(因为nf直接代表了一行有多少字段)
  • 倒数第二列可以写成($NF-1)

    awk内置变量

    image.png

    一次输出多列信息

    awk ‘{print $1,$2,$3}’ lianxi.txt awk ‘{print $1,$3,$2}’ lianxi.txt

awk是允许我们进行一次输出多列的,并且是可以定制内容信息的,顺序是由我们自己输入决定的,另外输出时我们可以利用逗号来进行隔开,不然内容是拼接在一起的。

自动定义输出内容

awk,必须外层单引号,内层双引号
内置变量$1、$2都不得添加双引号,否则会识别为文本,尽量别加引号。

awk ‘{print “第一列:”$1,”第二列:”$3,”第三列”$2}’ lianxi.txt

输出整行信息

awk ‘{print}’ lianxi.txt awk ‘{print $0}’ lianxi.txt

参数

-F 指定分割字段符
-v 定义或修改一个awk内部的变量
-f 从脚本文件中读取awk命令
image.png

案例

1.显示文件第五行

awk ‘NR==5{print $0}’ lianxi.txt

2.显示文件第2-5行

awk ‘NR==2,NR==5{print $0}’ lianxi.txt

3.给每一行的内容添加行号

添加变量,NR等于行号,$0表示一整行的内容

awk ‘{print NR,$0}’ lianxi.txt

4.显示文件第3-5行且输出行号

awk ‘NR==3,NR==5{print NR,$0}’ lianxi.txt

5.显示pwd.txt文件的第一列,倒数第二和最后一列

awk ‘{print $1,$(NF-1),$NF}’ pwd.txt

6.删除文件中的空白行

awk ‘!/^$/{print $0}’ lianxi.txt #print动作也可以不输入,效果一致

7.同时以空格和冒号作为分隔符

awk -F “[ :]” “{print $1 $2}” lianxi.txt

主要在于[ :],同时以空格和冒号进行了分割,更加的方便我们进行提取对应的内容

分隔符

awk的分隔有两种

  • 输入分隔符,awk默认是空格,空白字符,英文是filed separator,变量名是FS
  • 输出分隔符,output field separator,简称OFS

    FS输入分隔符

    awk逐行处理文本的时候,以输入分隔符为准,把文本切成多个片段,默认符号是空格
    当我们处理特殊文件,没有空格的时候,可以自由指定分隔符

    awk -F “:” ‘{print $1}’ lianxi.txt #更改为了以冒号为分隔符

  • 除了使用-F选项,还可以使用变量的形式,指定分隔符,使用-v选项搭配,修改FS变量,效果一样

    awk -v FS=”:” ‘{print $1}’ lianxi.txt

OFS输出分隔符

awk执行完命令,默认用空格隔开每一列,这个空格就是awk的默认输出符

输出的分隔符改为了’—-‘,(制表符\t)

awk -F “:” -v OFS==”—-“ ‘{print $1}’ lianxi.txt

变量

  • 内置变量
  • 自定义变量

image.png

内置变量

NR、NF、FNR

  • awk的内置变量NR、NF是不用添加$符号的
  • 而$0 $1 $2 …是需要添加$符号的

    这样我们可以打印多个文件的内容,但是这个时候,awk把两个文件当成了一个整体,行号是依次递增的

    awk ‘{print NR,$0}’ lianxi1.txt lianxi2.txt

    这个时候就用到了FNR变量,可以将两个文件的行号区分开来

    awk ‘{print FNR,$0}’ lianxi1.txt lianxi2.txt

RS、ORS

ORS是输出分隔符的意思,awk默认认为,每一行结束了,就得添加回车换行符
ORS变量可以更改输出符

将输出的内容,用空格就作为一个新的内容,遇到空格就换行

awk -v RS==’ ‘ ‘{print NR,$0}’ lianxi1.txt

在输出内容中,每一个换行符更换为新的内容

awk -v ORS==’@’ ‘{print NR,$0}’ lianxi1.txt

FILENAME

显示awk正在处理文件的名字

这个时候我们打印的时候,第一列会显示我们当前的内容是属于哪个文件的

awk ‘{print FILENAME,FNR,$0}’ lianxi1.txt lianxi2.txt

ARGC、ARGV

ARGV表示的是一个数组,数组中保存的是命令行所给的参数
数组是一种数据类型,如同一个盒子
盒子有它的名字,且内部有N个小格子,标号从0开始

这个时候打印出的内容,会先显示”我要开始用awk了”,再显示打印的具体的内容,这里是BEGIN的模块用法

awk ‘BEGIN{print “我要开始用awk了”} {print $0}’ lianxi.txt

这里面在视频当中ARGV依次显示了awk,文件名和空格,如果再加上一个文件进行同时处理的时候,发现[2]变成了第二个文件名

awk ‘BEGIN{print “我要开始用awk了”} {print ARGV[0],ARGV[1],ARGV[2]}’ lianxi.txt

自定义变量

顾名思义,就是我们自己定义变量

  • 方法一:-v varName=value
  • 方法二:在程序中直接定义
  • 方法三:间接引用shell脚本

    方法一:

    这里就是我们自己定义了一个变量myname,在之后输入的时候直接调用,打印出来的内容就是我们赋值的内容

    awk -v myname=”dzc” ‘BEGIN{print myname}’ 方法二:

    或者我们可以在打印的时候直接定义,也是可以的

    awk ‘BEGIN{print myname=”dzc”}’ 方法三:

    我们在终端直接赋值变量的时候,我们可以利用echo $变量,来打印变量,相应的,我们在awk定义的时候也是可以定义这个变量的

    dzc=”hahaha” echo $dzc —> hahaha awk -v myname=$dzc ‘BEGIN{print myname}’ —> hahaha

格式化

前面我们接触到的awk输出功能,是{print}的功能,只能对文本简单的输出,并不能美化或者修改格式。

printf格式化输出

在c语言和go语言当中,printf()函数也是文本格式化输出。(我没用过,,,就学过Python的print输出功能T.T)

printf和print的区别

  • 其与print命令的最大不同是,printf需要指定format
  • format用于指定后面的每个item的输出格式
  • printf语句不会自动打印换行符:\n

    format的使用

    format格式的指示符都是以%开头,后跟一个字符:
    %c:显示字符的ASCII码
    %d,%i:十进制整数
    %e,%E:科学计数法显示数值
    %f:显示浮点数
    %g,%G:以科学计数法的格式或浮点数的格式显示数值
    %s:显示字符串
    %u:无符号整数
    %%:即%本身

    printf修饰符:

    -:左对齐,默认右对齐
    +:显示数值符号,printf “%+d”

  • printf 动作默认不会添加换行符

  • print 默认添加空格换行符

    我们用printf打印出来的内容是一整行没有进行换行的

    awk ‘{printf $0}’ lianxi.txt

printf不同格式用法

1.分行输出

其实和print $0输出的内容是一样的

awk ‘{printf “%s\n”,$0}’ lianxi.txt

2.多个变量

这里面有几个%d\n,就会输出几个内容,因为awk里面每个字符段都要赋值一个格式命令

awk ‘BEGIN{print “%d\n%d\n%d\n”,1,2,3}’

3.如果是一个文本

等于给每列都加上了一个开头,再进行打印每行的内容

awk ‘{printf “第一列:%s 第二列:%s 第三列:%s\n”,$1,$2,$3}’ lianxi.txt

4.制作一个较为完善容易观看的表类型

awk ‘BEGIN{printf “%-10s\t %-10s\t %-10\n”,”姓名”,”学号”,”成绩”} {printf “%-10s\t %-10s\t %-10s\n”,$1,$2,$3}’ 9lianxi.txt

%s\t 格式化字符串后,添加制表符,四个空格(别忘了最后要换成\n,因为要换行了)
%-25s 依旧是格式化字符串内容,-代表左对齐,25代表25个字符长度

awk模式pattern

关于 BEGIN END 的具体解析,也是两种pattern的模式:

  • BEGIN模式是处理文本之前需要执行的操作
  • END模式是处理完所有行之后执行的操作

在之前的操作里面,BEGIN已经有了初步的了解,大致也就如此,而END也就是相反,一个开头输入,一个结尾输入
而模式我们也可以理解为是条件,awk默认是按行处理文本的,如果不指定任何模式(条件),awk默认一行行处理,如果指定了模式(条件),只有符合模式的才会被处理

  • 关于运算符,==、<、>、!=、~…之类的

awk与正则表达式

正则表达式主要与awk的pattern模式(条件)结合使用

  • 不指定模式,awk每一行都会执行对应的动作
  • 指定了模式,只有被模式匹配到的、符合条件的行才回执行动作
  1. 找出pwd.txt中以games开头的行

    一种我们可以用grep过滤

    grep ‘^games’ pwd.txt

    那么用awk我们也可以这样

    awk ‘/^games/{print $0}’ pwd.txt

语法:
grep ‘正则表达式’ pwd.txt
awk ‘/正则表达式/动作’ /etc/passwd
awk命令使用正则表达式,必须把正则放入“//”双斜杠中,匹配到结果后执行动作(print $0),打印整行信息。
当然awk能做到的还有更多,就好像awk功能更高级,但不代表他不能干低级的事情,虽然可能相比较grep繁琐一些,但是awk能做到的其他事情也是grep远远不能比肩的。

awk命令执行流程

解读:假如我们要从pwd.txt文件中,读取我们想要的需求内容

awk ‘BEGIN{ command } pattern{ command }END{ command }’ pwd.txt

  1. 优先我执行BEGIN{}模式中的语句
  2. 从pwd.txt文件中读取第一行,然后执行pattern{ command }进行正则匹配,如:/^n/寻找n开头的行,找到了执行{ print }进行打印
  3. 当awk读取到文件数据流的结尾时,会执行END{ command }