笔记 | awk 的知识点
awk
awk是一种处理文本文件的语言,用于Linux下对文本和数据进行处理。数据可以是标准输入、一个或多个文件、其他命令的输出。方式为逐行扫描,从第一行到最后一行,寻找到匹配特定模式的行进行操作。
命令格式和常用选项
命令格式
awk [options] ‘/pattern/{action}’ input-file
awk [options] -f myscript.awk input-file
常用选项
- -F 指定输入文件分隔符
- -f 从脚本文件中读取awk命令
- -v 赋值一个用户定义变量
模式
awk脚本是由模式和操作组成,模式可以是以下的几种:
- 正则表达式
- 关系表达式
- 模式匹配表达式
- BEGIN
- END
awk 'BEGIN {Fs = ":"; print "----header----"}/mail/{print $1} END{print “----footer----”}' /etc/passwd
#搜索包含关键字mail的行,并打印第一个字段
打印命令
awk '{print}' e
mployee.txt 传递变量 “ $字段序号 ” 作为print的参数
awk -F ',' '{print $2}' employee.txt
指定 , 为分隔符
模式匹配
awk -F ',' '/Manager/{print $2,$3}' employee.txt
awk 内置变量
FS - 输入字段分隔符 在BEGIN区域使用
OFS 输出字符分隔符
两种方式:
awk -F ',' '{print $2,":",$3}' employee.txt
awk -F ',' 'BEGIN{OFS=":"}{print $2,":",$3}' employee.txt
RS 记录分隔符
ORS 输出记录分隔符
NR 记录序号 条数
开始执行后,按照记录分隔符读取的数据次数,默认的记录分隔符为换行符,因此默认的就是读取的数据行数 Number of Record
NF 字段总数 Number of Field
FILENAME 当前处理的文件名
FNR 文件中的NR
变量操作符
变量
一元操作符 + 取正(返回数字本身) - 取反 ++ 自增 --自减
算术操作符
awk 'NR % 2 == 0' filename
取偶数
字符串操作符 “ ”
赋值操作符
比较操作符 && 且 ||或
正则表达式操作符 ~ 匹配 !~ 不匹配
分支和循环
- if 结构
if (conditional-expression)
action
多条 ;分割
awk '{if (NR % 2 ==0) ORS='\n';else ORS = ',';print}' filename
-
while 循环
while (condition)
Actions -
do - while 循环
进入控制判断的循环结构 -
for循环
for (initialization;condition;increment/decrement)
for循环一开始就执行 init 然后检查 con 如果为True,执行 action 然后 incre or decre
其他
printf
printf(format, value1, value2, ..., valuen)
可以灵活简单以你期望的格式输出结果
\n 换行 \t制表符 \v垂直制表符 \b退格 \r回车符 \f换页
格式化字符
s 字符串
c 单个字符串
d 数值
e 指数
f 浮点数
g 根据值决定使用e或f中较短的输出
o 八进制
x 十六进制
% 百分号
打印指定宽度(左对齐)
awk 'BEGIN {printf "%6s\n", "Good Boy!"}'
内置函数
内置函数
int(n) 整数
log(n) 返回给定参数的自然对数
sqrt() 正平方根
三角函数 sin() cos() atan2(m,n)
常用字符串函数
- index 函数
- length 函数 s 的长度
- split 函数
- substr 函数 substr (input-string,location,length) 子串 开始位置 总长度
对指定的正则表达式进行替换 - tolower(s) 转成小写
- toupper(s) 转成大写
- sub(f,r,s) 根据正则f 从r中提取数据到s
使用awk进行计算
关联数组
实现类似操作
cat filename cut -f '2' | sort | uniq -c | sort
这样的操作
awk '$1 ~ /Chr1/{feature[$3] += 1};END {for (k in feature) print k "\t" featrue[k]}' filename
练习
输入file.txt内容:
Mike Harrington:[510] 548-1278:250:100:175
Christian Dobbins:[408] 538-2358:155:90:201
Susan Dalsass:[206] 654-6279:250:60:50
Archie McNichol:[206] 548-1348:250:100:175
Jody Savage:[206] 548-1278:15:188:150
Guy Quigley:[916] 343-6410:250:100:175
Dan Savage:[406] 298-7744:450:300:275
Nancy McNeil:[206] 548-1278:250:80:75
John Goldenrod:[916] 348-4278:250:100:175
Chet Main:[510] 548-5258:50:95:135
Tom Savage:[408] 926-3456:250:168:200
Elizabeth Stachelin:[916] 440-1763:175:75:300
题目为:
- 显示所有电话号码
- 显示Dan的电话号码
- 显示Susan的名字和电话号码
- 显示所有以D开头的姓
- 显示所有以一个C或E开头的名
- 显示所有只有四个字符的名
- 显示所有区号为916的人名
- 显示Mike的捐款.显示每个值时都有以250175
- 显示姓,其后跟一个逗号和名,如Jody,Savage
- 显示第三列小于200的姓名
# 输入file.txt文件
# 这个文件是以 : 分割
# Vim编辑器,进入后按i,粘贴内容,按esc,输入 :wq 保存文件
$ vim file.txt
$ awk -F : '{print $2}' file.txt
# 精确匹配
$ awk -F : '$1~/Dan/{print $2}' file.txt
# 输出定义分隔符
$ awk -F: '$1~/Susan/{print$1":"$2}' file.txt
# ^行的开头 $行的结尾
$ awk '$1~/^D/{print $1}' file.txt
# 模糊匹配 或 || 且&&
$ awk -F: '$1~/^[C||E]/{print $1}' file.txt |awk '{print $2}'
# 变量
$ awk 'length($1)=="4"{print $1}' file.txt
# 替换 这里用sed也可以
$ awk -F"[ :]" '$3~/916/{print $1" "$2}' file.txt
# 定义输出形式
# 还有printf(format, value1, value2, ..., valuen)
$ awk -F: '$1~/Mike/{print "$"$3" ""$"$4" ""$"$5}' file.txt
# 条件
$ awk -F : '{if ($3<=200) print $1}' file.txt