awk简介
1.awk是一种编程语言,用于Linux下对文本和数据进行处理。数据可以来自:标准输入,文件,其他命令的输出命令,使用管道符
2、awk是以它的三位发明者姓名的首字母命名的
3.awk是一个行级文本的高效处理工具
4.awk的最大优势就是很灵活
awk语法格式:
awk+[Option] +脚本命令+filename
或使用管道符 df -hT |awk
常用option 以此命令为例
awk -F"\t" '{a[$2]+=$4}END{for(i in a) print i"\t"a[i]}'
-F 后面跟分隔符,以什么作为一行数据的分隔符,默认为空格,此例就是以\t作为分隔符
-f 后面指定脚本文件名,将脚本写入一个文件中,避免awk书写太长,使得不方便
-v 后面加变量
脚本命令:
awk的强大正是来源于它的脚本命令
脚本命令=匹配规则+执行命令
两者只可以有一个,但不可以一个没有,脚本命令必须用''括起来,当匹配规则为字符串和正则表达式的时候需要使用”/.../“符号括起来;而执行命令需要使用{}括起来,还有执行awk的时候如果不指定匹配规则
则默认匹配文中的所有行,如果不指定执行命令,则默认会把匹配到的所有行输出
awk的匹配规则
匹配规则可是以下的任意一个
1./正则表达式/:使用通配符的扩展集
2.关系表达式:使用运算符进行操作,可以是字符串或者数字的比较测试
3.模式匹配表达式:用运算符~和~!匹配和不匹配
BEGIN语句块,pattern语句块,END语句块
awk中分号和逗号的区别:
awk中如何打印单引号和双引号
awk脚本的基本结构
awk BEGIN{command} pattern{command} END{comman} filename
BEGIN 在AWK从输入流中读取行之前被执行,是可选的语句块,比如变量通常可以写在BEGIN语句块中
pattern 这个语句块中的通用命令是最重要的部分,但也是可选的,如果没有匹配到,则默认执行print即是打印每一个读取到的行
END语句块在awk从输入流中独取完所有行之后被执行,比如:打印完所需要的行之后,需要一个信息汇总情况,这个时候就可以卸载END语句里
awk的工作原理
第一步:执行BEGIN{}语句块中的语句
第二步:从文件或者标准输入stdin读取一行,然后执行pattern语句块,它将逐行扫描文件,从第一行到最后一行重复这个过程,之道文件全部被读取完毕
第三步:当读至输入流末尾,执行END语句块
awk中的变量
变量名 | 作用 |
---|---|
$0 | 执行过程中当前行 的所有文本内容 |
$n | 以xx为分隔符,当前行的第n个字段,$1为第一个字段… |
FS | 输入 字段 分隔符,默认为空白字符(搭配BEGIN语句块使用) |
OFS | 输出 字段 分隔符,默认为空白字符(搭配BEGIN语句块使用) |
RS | 输入 记录 分隔符,默认为换行符(搭配BEGIN语句块使用) |
ORS | 输出 记录 分隔符,默认为换行符(搭配BEGIN语句块使用) |
NR | 当前行号,从1开始;如果仅处理一个文件,可以将NR的值当为此文件的行号 |
FNR | 用法同 NR 一样,不过是用来处理多个文件 |
NF | 每一行中字段的总数 |
$NF | 每行中最后一个字段 |
$(NF-1) | 每行中的倒数第二个字段,以此类推 $(NF-2)为倒数第三 |
FILENAME | 当前正在被处理的文件的文件名,一般结合 END{print FILENAME}语句块使用 |
FILEWIDTHS | 由空格隔开iade定义了每个字段的宽度,即取代FS,由字段长度来决定如何分割字段的 |
ARGC | 命令行中参数的数量,包括 awk 自己。结合 END{commands}语句块使用 |
ARGV | 用法: END{print ARGV[0]} ,0表示命令行中的所有参数中的第一个,1为第二个 |
自定义变量
定义方式 -v var_name = value -v 变量名=值
内建变量的使用例子
1.$0,$n 由之前的例子可以知道,0代表输出整行,n代表打印该行的第几个字段
2FS和OFS
1.需要搭配BEGIN语句块使用,FS相当于-F参数,当FS与OFS(输出 字段 分隔符)在一起使用时,需要用;分开,当打印数据字段变为$0时,FS和OFS不生效
FS和OFS针对一行记录而言,RS和ORS 是对所有记录进行分割
输入 记录 分隔符,默认为换行符(搭配BEGIN语句块使用)
NR FNR NF使用说明
由图可知,当处理多个文件的时候,NR 会将多个文件的行号合并为一个文件的行号,而 FNR 会将多个文件的行号分开表示!
NF $NF $(NF-1)
FILENAME使用方法
awk常用的操作符
算数运算符 | |
---|---|
运算符 | 作用 |
+ - * / | 加、减、乘、除 |
% | 求余 |
+ - | 一元加减(正负号) |
++ -- | 增加 或 减少(前置或后置) |
^ | 次方 或 平方(a^2 : a的二次方) |
awk逻辑运算符
逻辑运算符 | ||
---|---|---|
运算符 | 作用 | 解释 |
&& | 逻辑和 | 双方都为真才成立 |
|| | 逻辑或 | 只要有一个为真就成立 |
! | 逻辑非(非真即假) | !true =flase |
awk赋值运算符
赋值运算符 | ||
---|---|---|
运算符 | 作用 | 举例 |
= | 单独一个等号就是赋值 | a=30 变量名=变量值 |
+= | … | a+=2,相当于 a=a+2 |
-= | … | a-=3,相当于 a=a-3 |
*= | … | … |
/= | … | … |
%= | … | … |
awk关系运算符 | |
---|---|
< <= > >= == != | 小于、小于等于、大于、大于等于、等于、不等于 |
awk正则运算符 | |
---|---|
~ | 匹配正则表达式 |
~! | 不匹配正则表达式 |
awk数组以及去重原理
在其他语言中,你可能习惯的提前声明数组,但是在 awk 中不需要提前声明,直接为 数组中的元素赋值即可!而且 awk 中使用 “数字下标” 的时候,默认是以 1 开始,并不是以0 开始,这里是因为一个函数(split),这边会在函数中提到具体为什么,以及如何使用。
数组的元素设置:
数组的元素设置为空 是允许的! 当你判断某个元素是否存在的时候,不应该看他数组元素是不是为空!
当一个元素不存在于数组 的时候,如果我们直接引用此不存在的数组元素,那么awk会自动创建这个元素并默认为此元素赋值为“空字符串”。
示例如下:
使用 awk for循环 和 数组 实现 去重功能:(sort 、uniq、tr 功能)
当"变量的值为字符串"的时候,也"可以进行自加运算",不过,"字符串会被当成数字0"来进行运算
然后,我们就可以利用这一点来统计某些字符出现的次数:
在上面的命令行中,使用了两个模式:"空模式 和 END模式";
在空模式中,我们随便创建了一个数组名为 “a” ,并将文件中“$2” 位置的值 作为了下标,进行引用;
当执行第一行的时候,我们引用的是 a["red"](文件中第一行第二个字段的值),很明显这个元素并不存在,所以:
其一开始的值为“0”,但是当第一行被处理完后,a["red"] 的值 已经被赋值为 1 了。
"由于 END 模式 中的动作会最后执行,所以我们先不考虑END模式;"
这时,空模式中的动作继续处理第二行,而第二行的第三个字段为"yellow",第一次出现的"颜色下标"参与运算的过程与上述同理!
然后当遇到相同的 "颜色下标" 的时候,他们对应的元素的值 都会 "+1","每遇到一次,就 +1"
直到处理完所有的行,开始执行 "END模式 中的 动作"
"此时,a数组中的下标为:第二字段,元素的值即为:第二字段出现的次数"
当然也使用 uniq 和 sort 来实现一下去重排序:
sort先进行排序,使得重复的行紧邻在一起,然后使用uniq去除相邻的重复行,-c选项,显示输出中,在每行行首加上本行在文件中出现的次数
AWK逻辑判断
1、这是 “if…else…” 的语法
{if($3<500){print}else{}}
if (条件)
{
语句1;
语句2;
…
}
else
{
语句1;
语句2;
…
}
2、这是 “if…else if…else” 的语法:
if (条件1)
{
语句1;
语句2;
…
}
else if(条件2)
{
语句1;
语句2;
…
}
else
{
语句1;
语句2;
…
}
for语句
格式1:
for (初始化;布尔表达式;表达式)
{
语句…
}
格式2:
for(变量 in 数组)
{
语句…
}
awk -F"\t" 'BEGIN{OFS="\t"};NR==FNR{a[$1]=$2;next;}NR>FNR{if($3 in a) print $0,a[$3]}' model_category dragon_data | awk -F"\t" '{a[$1]+=$4}END{for(i in a) print i"\t"a[i]}'
while 的语法格式:
while(布尔表达式){
语句…
}
do while 循环语法:
do {
代码语句…
}
while(条件)
while 循环实例:
continue,break,exit,next,next使用
nextfile —— 跳过当前文件
nextfile 表示: 在某条件的时候跳过,但是不再执行此文件,立马跳到下一个文件执行!但是下一个文件执行的话,使用的还是同一个条件!
关于print与printf的使用
关于 print
print 我们都知道,它是 awk 中最常用的动作,根据 awk 的匹配规则,匹配到需要的数据,然后使用 print 打印出来!
print在打印字段的时候,需要使用 “,”(逗号) 隔开字段 ,各个字段都会 自动转换成字符串格式,然后根据 自定义的内置变量“OFS”(默认值为 空格) 的值来连接输出的各个字段的字符串!
print 要输出的数据被称之为 “记录”,在print 输出时,会在后面自动加上 输出记录分隔符“ORS” ,它的值默认为换行符 “\n”。
关于printf
准确的说,printf 是根据我们自己设定的格式来输出文本。然鹅,说到输出文本,就会想到另一个常用输出命令:echo。
很清楚的看到,echo 自动给输出的文本进行换行,而 printf 却没有。如果想换行只能结合换行符 “\n”来换行。
关于 格式化字符:
提到了 printf 就要说说它的搭档们了 —— “格式化字符”。基本上跟C语言中的格式化输出一致
格式替换符 | 作用 |
---|---|
%s | 字符串 |
%f %F | 浮点格式 |
%g %G | 浮点格式 或 科学计数格式(输出为数字自己本身) |
%b | 相对应的参数中包含转义字符时,使用此符号进行替换,对应的转义字符就会被转义 |
%c | 显示对应参数的第一个字符 |
%d %i | 转换为 整数,但不是四舍五入的结果(23.999 会输出为 23) |
%o | 将 正整数 识 别为八进制数,然后再转换为十进制的方式输出 |
%u | 十进制 … … … … |
%x %X | 十六进制 … … … … … |
%% | 表示 % 本身 |
1、关于 %s 的用法:
2、关于 %f/F 的用法:
3、关于 %g %G 的用法:
4、关于 %c 的用法:
....
AWK内置字符串函数
函数 | 说明 |
gsub( Ere, Repl, [ In ] ) | 除了正则表达式所有具体值被替代这点,它和 sub 函数完全一样地执行,。 |
sub( Ere, Repl, [ In ] ) | 用 Repl 参数指定的字符串替换 In 参数指定的字符串中的由 Ere 参数指定的扩展正则表达式的第一个具体值。sub 函数返回替换的数量。出现在 Repl 参数指定的字符串中的 &(和符号)由 In 参数指定的与 Ere 参数的指定的扩展正则表达式匹配的字符串替换。如果未指定 In 参数,缺省值是整个记录($0 记录变量)。 |
index( String1, String2 ) | 在由 String1 参数指定的字符串(其中有出现 String2 指定的参数)中,返回位置,从 1 开始编号。如果 String2 参数不在 String1 参数中出现,则返回 0(零)。 |
length [(String)] | 返回 String 参数指定的字符串的长度(字符形式)。如果未给出 String 参数,则返回整个记录的长度($0 记录变量)。 |
blength [(String)] | 返回 String 参数指定的字符串的长度(以字节为单位)。如果未给出 String 参数,则返回整个记录的长度($0 记录变量)。 |
substr( String, M, [ N ] ) | 返回具有 N 参数指定的字符数量子串。子串从 String 参数指定的字符串取得,其字符以 M 参数指定的位置开始。M 参数指定为将 String 参数中的第一个字符作为编号 1。如果未指定 N 参数,则子串的长度将是 M 参数指定的位置到 String 参数的末尾 的长度。 |
match( String, Ere ) | 在 String 参数指定的字符串(Ere 参数指定的扩展正则表达式出现在其中)中返回位置(字符形式),从 1 开始编号,或如果 Ere 参数不出现,则返回 0(零)。RSTART 特殊变量设置为返回值。RLENGTH 特殊变量设置为匹配的字符串的长度,或如果未找到任何匹配,则设置为 -1(负一)。 |
split( String, A, [Ere] ) | 将 String 参数指定的参数分割为数组元素 A[1], A[2], . . ., A[n],并返回 n 变量的值。此分隔可以通过 Ere 参数指定的扩展正则表达式进行,或用当前字段分隔符(FS 特殊变量)来进行(如果没有给出 Ere 参数)。除非上下文指明特定的元素还应具有一个数字值,否则 A 数组中的元素用字符串值来创建。 |
tolower( String ) | 返回 String 参数指定的字符串,字符串中每个大写字符将更改为小写。大写和小写的映射由当前语言环境的 LC_CTYPE 范畴定义。 |
toupper( String ) | 返回 String 参数指定的字符串,字符串中每个小写字符将更改为大写。大写和小写的映射由当前语言环境的 LC_CTYPE 范畴定义。 |
sprintf(Format, Expr, Expr, . . . ) | 根据 Format 参数指定的 printf 子例程格式字符串来格式化 Expr 参数指定的表达式并返回最后生成的字符串。 |