Linux 命令工具之 awk
一、awk 介绍
二、awk 命令基础使用
三、常用内置变量和运算符以及内置函数
四、awk 最佳实践
awk 是一种编程语言
,用于在 linux/unix 下对文本和数据进行处理。支持 if 判断分支和 while 循环语句还有它的内置函数等,是一个要比 grep 和 sed 更强大的文本处理工具。
awk 处理文本和数据的方式:它逐行扫描文件
,从第一行到最后一行,寻找匹配的特定模式的行,并在这些行上进行你想要的操作。如果没有指定处理动作,则把匹配的行显示到标准输出 (屏幕),如果没有指定模式,则所有被操作所指定的行都被处理。
awk 作为一种编程语言,作用是做报表,日志分析等等。
1. 使用方式
注意: awk 可以使用命令行方式和脚本方式对文本文件进行处理
2. 命令选项
-F
: 指定输入文件处理的分隔符,默认为空格-v var=value
: 从 shell 脚本传递变量到 awk 脚本中-f|--file scriptfile
: 从脚本文件中读取 awk 命令注意
awk 脚本内容分为 BEGIN区、正文区、END区
。其中 BEGIN 区 更多的用于处理数据的头文件,比如表头;而 END 区 一般用于处理汇总信息,比如表格的总计信息。
在脚本首行需要指定 解释器。
$ cat test.awk
#!/usr/bin/awk -f
BEGIN{ print "start..."
FS=":"
}
{ print $1" "$2}
END{ print "end..."}
# 执行awk 脚本
$ awk -f test.awk /etc/passwd
内置变量
变量 | 作用描述 |
---|---|
$n | 当前记录的第 n 个字段 |
$0 | 匹配到的整行完整记录 |
FS | 字段分割符号 (等同于 -F ) |
NF | 当前记录的字段数 (也可以直接当做列数 ) |
NR | 当前记录行数 |
OFS | 输出字段分割符 |
ARGC | 命令行参数的树木 |
FIELDWIDTHS | 字段宽度列表 (用空格键分隔) |
FILENAME | 当前文件名 |
FNR | 同 NR,但相对于当前文件 |
运算符
运算符 | 作用描述 |
---|---|
= 和 += 和 -= 和 *= 和 /= 和 %= 和 ^= 和 ** | 计算赋值 |
?: | C 条件表达式 |
|| 和 && | 逻辑运算 |
~ 和!~ | 正则表达式 |
< <= > >= != == | 关系运算符 |
空格 | 连接 |
+ - * / & | 数学计算 |
$ | 字段引用 |
内置函数
函数 | 作用 |
---|---|
delete arr[1] | 删除指定下表的元素 |
length(str) | 获取字符串长度 |
index(string,"abc") | 获取字符串 string 中 abc 的索引 |
tolower(string) | 字符串小写转换 |
toupper(string) | 字符串转换为大写 |
substr(string,start,length) | 截取字符串 string |
match(string,/[0-9]/) | 正则匹配字符串,匹配结果存储在内置变量 RSTART |
sub(regex,regexstring,string) | 把 string 中包含 regex 的字符串替换为 regexstring |
gsub(r,s) | 用 s 代替 r,范围全文本 |
gsub(r,s,t) | 范围 t 中,s 代替 r |
split(string,string_arr," ") | 把 string 按照空格分割,存储在 string_arr 中;nums=split ("a,b,c,sdfd,se",myeles,",") 可以表示数组元素个数 |
编程语句
# awk 处理过程中每一行成为一个记录,$0 表示整行记录,NR 表示一个计数器,即读取到的行数
## 依次读取test.txt 文件中的每一行并输出行号和内容
$ awk '{print NR,$0}' test.txt
# 获取行数 借用awk 按行读取的特性,每读一行进行一次自增
$ awk '{line++} END{print line}' /etc/passwd
# 指定分隔符
## 快速获取Linux系统中的用户名称
awk -F ':' '{print $1}' /etc/passwd | head
# 倒数第二列
awk '{print $(NF-1)}' test.txt
# 整个文本最后一列
awk '{print $NF}' test.txt
#遍历文件的所有单词
$ awk '{for(i=1;i<=NF;i++) {print $i}}' test.txt
# 打印99乘法表
awk 'BEGIN {for(i=1;i<9;i++) {for(j=1;j<9;j++) {biao[i,j] = i*j;print i,"*",j,"=", biao[i,j];} }}'
# 使用linux shell 命令
## 注意: 等同于 awk 'BEGIN {FS = ":"} {print $1 }' /etc/passwd | sort
awk 'BEGIN {FS = ":"} {print $1 | "sort"}' /etc/passwd
# 匹配行内容
## 同理可以支持模糊匹配 '$0 ~ /(class-1|student-1)/'
awk '$0 ~/class/' filename
# 精准匹配域
## 同时也可以反向匹配 '$7!="class-2" {print $0}'
awk '$7=="class-1" {print $0}' filename
# 匹配列并进行计算
awk '$1 ~ /lg/ {mem = $2 * $3; print mem}' filename
awk '$1 ~ /cls/ {clusterID=$1; print $1" "$2}' filename
# 正则匹配并打印和计算列
awk -F ':' '/^root/{print $0}' /etc/passwd
awk -F ':' '/^root/{print $3+1}' /etc/passwd
# 获取第二列大于60的数据
awk '$2>60 {print $0}' filename
# 获取第二列大雨第4列的数据
awk '$2 > $4 {print $0}' filename
# 复合表达式
## 获取第二列大于60且第三列大于60的数据
## 同理或 '{ if ($2 > 80 || $4 > 80) print $0}'
awk '{ if ($2 > 60 && $3 > 60) print $0}' filename
awk 'BEGIN{str_tmp="it is a test";split(str_tmp,str_arr," ");for(k in str_arr){print k,str_arr[k];}}'
注意
:split 是 awk 内置的函数,split(str_tmp,str_arr," ")
可以将 str_tmp 变量按照空格分割后赋值到 str_arr 的数组变量中。(split 街区的数组下标从 0 开始)