玩转Linux Shell编程(六)、文本处理之awk

445 阅读2分钟
  1. Linux Shell和基本指令
  2. Bash shell语法
  3. 正则表达式
  4. 文本处理之grep
  5. 文本处理之sed
  6. 文本处理之awk
  7. Text GUI编程
  8. Tomcat启动脚本分析
  9. gradlew脚本分析

awk是一种处理文本文件的工具,和 sed 命令类似,awk 命令也是逐行扫描并处理的,也就是将寻找含有目标文本的行,如果匹配成功,则会在该行上执行用户想要的操作。

awk 命令的基本格式为:

$  awk [选项] '脚本命令' 文件名

选项:
F fs	指定以 fs 作为输入行的分隔符,awk 命令默认分隔符为空格或制表符。
-f file	从脚本文件中读取 awk 脚本指令,以取代直接在命令行中输入指令。
-v var=val	在执行处理过程之前,设置一个变量 var,并给其设备初始值为 val。

awk 的强大之处在于脚本命令,它由 2 部分组成,分别为匹配规则和执行命令,如下:

'匹配规则{执行命令}'

匹配规则用来指定脚本命令可以作用到文本内容中的具体行,比如 /abc/,表示处理含有 abc 字符串的行,或者通过正则表达式。

而整个脚本命令是用单引号' '括起,其中的执行命令部分需要用大括号{}括起来。

变量

默认情况下,awk 会将如下变量分配给它在文本行中发现的数据字段:

-   $0 代表整个文本行;
-   $1 代表文本行中的第 1 个数据字段;
-   $2 代表文本行中的第 2 个数据字段;
-   $n 代表文本行中的第 n 个数据字段。

这里的数据字段指的是以空格(默认情况)分割的字符,比如一行的数据是ab cd ef ,那么这里就有3个数据字段,分别是abcdef,在awk中分别以$1$2$3代表,这种变量比较常用。

还有其他变量如下所示。

变量描述
FS字段分隔符 (默认是空格)
OFS输出字段的分隔符(默认是空格)
RS行分隔符(默认以\n作为一行的结尾),单行分割成多行用到
NR行号,从1开始,多文件时候也是连续接着计数
FNR各文件分别计数的行号,多文件的时候会和NR不同,它会重新计数
NF一行中字段数量,最后一个字段内容可以用$NF取出
ARGC命令行参数的数目
ARGV包含命令行参数的数组,第一个参数是命令awk

示例

打印所有行

$ cat 1.txt 
One Text
Two Text
Three Text

$ awk '{print $0}' 1.txt
One Text
Two Text
Three Text

只打印某数据字段

$ awk '{print $1}' 1.txt 
One
Two
Three

这里的$1表示每行中以空格分开的第一个数据字段,以此类推,也可以同时指定多个。

$ awk '{print $0,$1,$2}' 1.txt 
One Text One Text
Two Text Two Text
Three Text Three Text

匹配指定开头的行

如下使用正则,^1表示处理以1开头的行。

$ cat 1.txt 
abc 666
123 777
1234 999
321 333
$ awk '/^1/{print $2}' 1.txt 
777
999

统计字段数量

$ awk '{print NF}' 1.txt 
2
2
2
2

从date中获取某字段

$ date
2022年 07月 10日 星期日 18:43:37 CST
$ date | awk '{print $5}'
18:44:09

改变输出分割符号

默认输出时候,也是以空格为单位,可以通过OFS="-"指定将以-为单位。

$ date | awk 'OFS="-" {print $4,$5}'
星期日-18:46:59

匹配条件

如下,通过条件判断只显示工资大于1000的人员姓名。

$ cat 1.txt 
张三 1200
李四 800
王五 2000
$ awk '$2 > 1000 {print $1}' 1.txt 
张三
王五

if else

$ awk '{if (NR % 2==1){print "奇数行 "$1} else {print "偶数行 " $1}}' 1.txt 
奇数行 张三
偶数行 李四
奇数行 王五

获取UID大于等于1000的用户

$ awk -F: '$3 >= 1000 {print $1}' /etc/passwd
nobody
hxl

使用内置函数

awk中内置了大量函数,这里就不一一说明.

systime

作用:获取当前时间戳

$ awk 'BEGIN {print systime()}'

substr

作用:截取字符串

$ echo "abcdef" | awk '{print substr($0,0,3)}'
abc

int

作用:转整型,直接省略小数点后面的部分。

$ echo 12.6 |awk '{print int($0)}'
12

rand

作用:随机数

$ echo 12.6 |awk '{print rand()}'
0.767772

BEGIN、END

awk中还有两个关键字BEGIN、END,类似于回调,分别在开始执行时候回调和执行结束后回调。

1. BEGIN{}	: 最开始执行
2. {}		: 正文
3. END{}	: 最后执行

如下

$ awk 'BEGIN {print "开始"} {print $1} END{print "结束"}' 1.txt
开始
张三
李四
王五
结束

获取行号

如现在只想打印奇数行,可以通过内置变量NR获取

$  awk 'NR % 2==1{ print $1}' 1.txt
张三
王五

获取行长度

$ awk 'length($0)>=8 {print "本行长度为:" length($0) "  "$0}' 1.txt 
本行长度为:8  def 4566

自定义变量

通过-v参数设置一个变量a,值为100,在打印时候将数据段2分别在加上变量a。

$ cat 1.txt 
abc 12
def 45
$ awk -va=100  '{print $2+a}' 1.txt 
112
145

查看tcp状态为ESTABLISHED的所有连接

$ netstat -an | awk ' BEGIN {print "本地   远程" } $1=="tcp" && $6=="ESTABLISHED"{print $4 " " $5} END {}'

获取所有java进程的id

$ ps -ef |grep java |  awk '{print $2}'
23763
24328

统计当前目录文件所有大小

$ ls -l | awk -vsum=0 'BEGIN {} {sum+=$5} END{print sum/1024/1024"MB"}'