强大的awk指令
1. awk简介
awk 是一个强大的文本分析工具,它是 Linux 中功能强大的数据处理引擎之一,可能这么说非常抽象,awk 可以非常轻松地处理比如每行都是相同格式的文本,比如日志,cvs 格式等等。相对于 grep 的查找,sed 的编辑,awk 在其对数据分析并生成报告时,显得尤为强大。本文,只是简单介绍如何使用awk完成简单的日常任务需求。
2. awk特性
- 语句格式
# 统配模式 awk [options] 'script' file
options
这个表示一些可选的参数
选项,script
表示 awk 的可执行脚本代码
(一般被{}
花括号包围),这个是必须的。file
这个表示 awk 需要处理的文件,注意需要是纯文本文件
(意味着 awk 能够处理)。# 传统模式 awk [options] 'BEGIN{statement} {statement} END{statement}' file
BEGIN: 在脚本代码段前面使用 BEGIN 关键字时,它会在开始读取一个文件之前,运行一次 BEGIN 关键字后面的脚本代码段, BEGIN 中的脚本代码段只会执行一次,执行完之后 awk 程序就会退出。
END: awk 的 END 指令和 BEGIN 恰好相反,在 awk 读取并且处理完文件的所有内容行之后,才会执行 END 后面的脚本代码段。 - 内置变量
awk中,常见和使用最为频繁的内置变量都在下面列举了出来:
1)NR: 表示文件中的行号,表示当前是第几行。
2)NF: 表示文件中的当前行被分割的列数,可以理解为 MySQL 数据表里面每一条记录有多少个字段,所以 NF就表示最后一个字段,(NF-1) 就表示倒数第二个字段。
3)FS: 表示 awk 的输入分隔符,默认分隔符为空格和制表符,可以对其进行自定义设置。
4)OFS: 表示 awk 的输出分隔符,默认为空格,也可以对其进行自定义设置。
5)FILENAME: 表示当前文件的文件名称,如果同时处理多个文件,它也表示当前文件名称。
6)RS: 行分隔符,用于分割行,默认为换行符。
7)ORS: 输出记录的分隔符,默认为换行符。
8)$符取值:$0
表示当前行中的数据。\$1,$2,$3...
表示当前行中的第一列,第二列数据,第三列数据… - 内置函数
awk 还提供了一些内置函数,在 awk 的 script 中编写脚本代码的时候,可以直接进行调用。比如:- toupper() 用于将字符转为大写
- tolower() 将字符转为小写
- length() 长度
- substr() 子字符串
- sin() 正弦
- cos() 余弦
- sqrt() 平方根
- rand() 随机数
- 运算符
awk中的常见运算符有:赋值: =
算术:+ - * / %
比较:< <= == != > >= ~ !~ 。~ 表示正则
。
逻辑:&& || !
3. awk技巧
- AWK使用的RE为ERE
- 如果在BEGIN中设置了OFS, 只有$0有改动OFS才能生效
- printf与print的区别: printf不自动打印换行符, print则自动打印
- gsub的返回值并不是替换后的字符串,而是返回替换的次数
- 字符串常量一定在用” “包围起来,否则当作变量使用, 如$1==“ipaddress”
- AWK 的 for 循环为C-Style,即为for(),区别于shell中的for i in …
- AWK中可以使用多个分隔符,要封装在方括号里,用’ ‘包围,以防shell对它们进行解释,如awk -F ‘[ :/t]’,使用空格,冒号,tab作为分隔符
- next语句:从输入文件中取得下一个输入行,在AWK命令表顶部重新执行命令,一般用于跳过一些特殊的行
- awk 匹配多个条件:awk ‘/kobe/ && /james/’,这会匹配同时有kobe和james的行
- FS的默认值是[ /t/n]+, OFS的默认值为空格,RS,ORS的默认值都是换行
- exit语句:终止AWK程序,但不跳过END语句
- {s1;s2;s3;…}中多个语句用分号隔开if; else if; else
- print后不带任何参数时,相当于print $0,将会打印整行记录
运用awk
1. if,for语句
在使用 awk 读取文件或者文件,或者文本的时候,我们需要在遍历每一列,并将符合要求的列中的数据进行输出。那么我们就需要使用到 for 语句与 if 语句。具体语句用法同 shell 有区别。
- for循环写法:
#{}中用分号分隔多个动作 for(i=1;i<=NF;i++){action1; action2; ..} #for后接一个if结构 for(i=1;i<=NF;i++) if; else if;else #简单的循环打印 for(i=1;i<=NF;i++) printf "for add"
- if判断写法:
#else if部分可以没有 if($1 ~ /reg/){action1}; else if($1 ~ /reg2/){action2}; else{action3} #多个条件用”&&”,”||”表示 if($1 ~ /reg/ && $2 ~ /reg2/){action} if($1 ~ /reg/ || NR >= 5){action}
2. 小案例
开始小案例的演示工作之前,我们需要准备份文本数据,方便指令要操作完成小案例。样例数据(sample_data.txt):
this is sample data
i love shell program
2020 8 14 16 29
apple banana mango orange
so happy today
有了样本数据,那么我们就可以开始操作了,由于篇幅有限,只做个别演示。
- 读取文本中的每一行数据,并显示行号。
awk '{print NR "\t" $0}' sample_data.txt
- 输出每一行中的第1,2,4列。
awk '{print NR "\t" $1 " " $2 " "$4}' sample_data.txt
- 第3行,将它格式化为日期,输出形式:202-08-16。
awk ' NR == 3 {$2='0'$2; print $1 "-" $2 "-"$4}' sample_data.txt
- 尝试处理文本,组合输出:i love eat apple的文本。
awk 'BEGIN{res="";} {if(NR == 2){res=$1" "$2;}else if(NR == 4){res=res" eat "$1;}} END{print res;}' sample_data.txt
有关 awk 的操作太多了,对于具体的需求,就需要具体使用了。关于 awk 的更多新技能,那就需要在使用的过程中慢慢探索咯。
编码实践是最有效,最高效的学习技能!
希望我们可以一起学习,一起编码,一起成长进步!