1. awk
awk是操作数据并创建报告的语言。
awk可以在命令行使用简单的运算符,也可以用于高级程序。awk可以操作数据,是shell脚本不可或缺的工具,也用于管理低级数据库。
[qwe@localhost ~]$ whereis awk
awk: /bin/awk /usr/bin/awk /usr/libexec/awk /usr/share/awk /usr/share/man/man1/awk.1.gz /usr/share/man/man1p/awk.1p.gz
[qwe@localhost ~]$ which awk
/usr/bin/awk
[qwe@localhost ~]$ awk --version
GNU Awk 3.1.7
Copyright (C) 1989, 1991-2009 Free Software Foundation.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see http://www.gnu.org/licenses/.
2.awk编程格式
进行awk编程的时候,先输入awk指令,然后输入带单引号的模式或动作,最后输入文件。
2.1 从文件输入
[qwe@localhost awk]$ cat awkfile
洪 吉童 3324 5/11/96 50354
林 巨正 5246 15/9/66 287650
李 成桂 7654 6/20/58 60000
丁 若涌 8683 9/40/48 365000
[qwe@localhost awk]$ awk '{print $1, $2}' awkfile
洪 吉童
林 巨正
李 成桂
丁 若涌
[qwe@localhost awk]$ awk '{print $5}' awkfile
50354
287650
60000
365000
2.2 从指令输入
使用“|”管道,可以从指令输入。
[qwe@localhost awk]$ df
Filesystem 1K-blocks Used Available Use% Mounted on
/dev/sda2 18306828 3260180 14116704 19% /
tmpfs 515264 228 515036 1% /dev/shm
/dev/sda1 297485 32799 249326 12% /boot
[qwe@localhost awk]$ df | awk '$4>1000000'
Filesystem 1K-blocks Used Available Use% Mounted on
/dev/sda2 18306828 3260172 14116712 19% /
2.3 awk工作原理
* 首先,awk通过文件或管道获取输入行,然后向$0内置变量输入行。各行称为“记录”。
* 然后,行以空格分隔为每个字段或词。各字段保存为变量并赋予编号,从$1开始。能够保存超过100个字段。
* awk有个叫作“FS内置变量”的字段分隔符,FS最先分配空格。若使用冒号或者别的符号分隔字段,则可以由新字段分隔符更改FS的值。
* awk使用print函数在画面上显示字段。
* 画面上显示awk后,调用文件的下一行,并保存为$0。此时,覆盖之前保存在$0变量的行,再用空格分隔字段进行处理。
2.4 print函数
awk命令的动作部分使用花括号({ })。若未指定动作而匹配模式,awk就执行默认动作,在屏幕上显示匹配行。使用print函数显示内容时无需格式化。
awk动作部分中,print函数可以使用{print}格式。print函数可以使用参数变量计算出的值或字符串常数,字符串需使用双引号(“ ”)。
[qwe@localhost awk]$ date
Sun Apr 12 00:50:24 PDT 2020
[qwe@localhost awk]$ date | awk '{print "Today is " $1 "day" "现在时间" $4 }'
Today is Sunday现在时间00:51:46
print函数的转义字符:
\b 退格
\f 换页符
\n newline下一行
\r 回车
\t Tab
\c c代表字符
2.5 OFMT变量
显示数字需要控制数字格式,可以使用printf函数,也可以使用OFMT变量。使用print函数时,可以利用OFMT变量控制数字显示格式。默认格式设置为%.6g,该格式最多包括6位数,若以“0.”开始则显示小数点后面的6位数,否则显示6位数。
[qwe@localhost awk]$ awk 'BEGIN{print 0.1234556,15E-3}'
0.123456 0.015
[qwe@localhost awk]$ awk 'BEGIN{print 1.23394944043}'
1.23395
[qwe@localhost awk]$ awk 'BEGIN{OFMT="%.2f";print 1.2333,15E-3}'
1.23 0.01
2.6 printf函数
printf函数通过标准输出返回已格式化字符串。printf语句拥有格式指示符和修饰符等控制字符串,控制字符串由逗号和逗号分隔的表达式的目录决定。
printf格式字符:
c 字符
s 字符串
d 十进制数
ld Long十进制数
u Unsigned十进制数
x 16进制数
lx Long 16进制数
o 八进制数
lo Long八进制数
e 指定的批注中的实数
f 实数
g 即使输入使用e或f的实数也包含空格
[qwe@localhost awk]$ awk '{printf "The name is %-20s Number is %4d\n",$1" "$2,$3}' awkfile
The name is 洪 吉童 Number is 3324
The name is 林 巨正 Number is 5246
The name is 李 成桂 Number is 7654
The name is 丁 若涌 Number is 8683
“%-20”,表示从左侧开始显示20个字符。
2.7 awk -f 选项
若文件中已生成awk动作和命令,则使用-f选项。awk命令保存在特定文件中,使用-f选项在该文件中使用输入命令处理其他文件。格式:awk -f [awk命令文件][awk命令适用文本文件]
2.8 记录和字段
awk不能查看输入数据,但可以查看格式和结构。默认每行称为“记录”,由newline分隔。
记录分隔符:默认设置的输出和输入记录分隔符是回车,保存在内置awk变量ORS和RS中。虽然可以更改,但最好不这么做。
$0变量:awk中的所有记录都被浏览为$0.
[qwe@localhost awk]$ awk '{print $0}' awkfile
洪 吉童 3324 5/11/96 50354
林 巨正 5246 15/9/66 287650
李 成桂 7654 6/20/58 60000
丁 若涌 8683 9/40/48 365000
NR变量:每个记录号保存于awk内置变量NR。记录保存后,NR值就加1。
[qwe@localhost awk]$ awk '{print NR,$0}' awkfile
1 洪 吉童 3324 5/11/96 50354
2 林 巨正 5246 15/9/66 287650
3 李 成桂 7654 6/20/58 60000
4 丁 若涌 8683 9/40/48 365000
字段:每个记录默认由词构成,所谓的词由空格或者Tab分隔的字段组成,每个词称为1个字段。awk保持内置变量NF的字段数,每行NF值一般可拥有100个字段。
[qwe@localhost awk]$ awk '{print $0,NF}' awkfile
洪 吉童 3324 5/11/96 50354 5
林 巨正 5246 15/9/66 287650 5
李 成桂 7654 6/20/58 60000 5
丁 若涌 8683 9/40/48 365000 5
字段分隔符:awk内置变量FS拥有输入字段分隔符的值。
2.9 模式和动作
模式:awk模式管理awk在输入行的动作,该模式由正则表达式、真和假状态结果或二者结合组成。
动作:awk动作是使用花括号({ })的语句,以分号分隔。模式在动作之前,动作可创建为简单语句或高级语句组。
3. 正则表达式
awk支持的元字符如下:
^ 匹配字符串的开头
$ 匹配字符串的末尾
. 匹配1个字符
* 匹配0及0个以上字符
+ 匹配1个及多个字符
- 匹配0个或1个字符
[ABC] 匹配其中一个字符
[^ABC] 之中无匹配字符
[A-Z] A-Z范围内存在匹配字符
A|B 匹配A或B
(AB)+ 匹配多个AB字符集
\* 匹配(*)字符
& 在检索字符串中用检索出的字符串代替
match运算符:标记波浪线(~)的match运算符检查某个记录或字段是否匹配表达式。
[qwe@localhost awk]$ awk '$2~ /[Jj]itong/' awkfile2
hong jitong 3324 5/11/96 50354
5. 比较表达式
比较表达式检索的行只有在状态显示为真时才能执行动作,该表达式使用关系运算符比较数字或字符串。
< 小于
<= 小于等于
== 等于
!= 不等于
>= 大于等于
> 大于
~ 匹配正则表达式
!~ 与正则表达式不匹配
算术运算符如下:
+ 加法 - 减法 * 乘法 / 除法
% 取余 ^ 乘方
逻辑运算符和混合模式
&& 逻辑和 || 逻辑或 ! 逻辑非
6. awk变量
6.1 数值与字符串常数
数值分为123等整数型和3.14等实数型,也可以使用.123E-1或1.2e3等科学符号。
awk程序可添加变量。字符串、数字、数字和字符结合的值都能成为变量。若没有变量,则成为“=”符号右侧表达式的类型。
6.2 用户自定义变量
awk不会另外定义用户自定义变量,但可在表达式中根据变量上下文预测数据类型。若不初始化变量,awk就将字符串 变量和数字型变量分别初始化为null和0。
增量运算符(++)和减量运算符(--)
命令行的用户自定义变量:可以在命令行给变量分配值,并传递给awk脚本。
awk -f awkfile -v month=8 year=2008 filename
字段变量:除参考字段之外,字段变量可用作用户自定义变量。通过分配值可以创建新字段,若可以浏览字段值且不赋值,则分配null字符串。
awk '{$3=100 * $2/$1; print }' filename //文件不存在$3则创建,如果存在则覆盖原来的值
6.3 BEGIN模式
awk处理处输文件的行之前执行BEGIN模式,将其置于动作块前。若awk未完成BEGIN动作块,则BEGIN块不读取输入内容,所以输入文件不存在也可测试。
BEGIN动作通常用于更改内置变量(OFS、RS、FS等)、分配用户自定义变量的初始值,并常作为输出的一部分用于打印头文件或标题。
6.4 END模式
END模式不输入任何输入行,但执行END模式相关动作。先处理所有输入行,然后处理END模式。
7. awk重定向
输出重定向: 将awk的结果重定向至Linux文件时,使用shell重定向运算符。但是,此文件名必须使用双引号。
[qwe@localhost awk]$ awk -F: '$5 >= 100000 {print $1,$2 > "newfile"}' awkfile
输入重定向:使用getline函数从标准输入、管道、当前处理的文件读取输入内容。在输入的下一行设置NF、NR、FNR内置变量。getline函数检索到记录则返回1,检索文件末尾则返回0。若发生错误,getline函数返回-1,表示文件打开失败。
[qwe@localhost awk]$ awk 'BEGIN{ "date" | getline d;print d}'
Sun Apr 12 03:02:51 PDT 2020
//执行linux指令date,用管道连接命令结果。然后向用户自定义变量d分配getline的结果值,并显示d的值。
8. awk管道
在awk程序中打开管道时,打开其他管道前先关闭已打开的管道。管道符号右侧命令必须使用双引号(“ ”)。每个管道只能打开一次。
[qwe@localhost awk]$ awk '{print $1,$2 | "sort -r"}' cars //sort命令使用-r选项,表示逆序排列。
zsdddd
sonate
qwelss
pride
m5
[qwe@localhost awk]$ cat cars
m5
sonate
qwelss
zsdddd
pride
关闭文件和管道:需要关闭第一个管道才能重新读写awk程序的文件或管道,因为脚本结束前会一直保持打开状态。文件或管道一旦打开就会一直保持开启状态,直到awk终止,所以end块的语句受管道影响。
system函数:内置函数执行包含参数的Linux系统命令,并向awk程序返回终止状态。
system("Linux 指令")
9. 程序管理语句
9.1 next语句
next语句从输入文件获取输入的下一行,从awk脚本开始部分重新执行。
[qwe@localhost awk]$ awk -f awkscript3 awkdata1
Tom 85 88
Mary 74 98
[qwe@localhost awk]$ cat awkdata1
Tom 85 88
Jane 91 -1
Mary 74 98
[qwe@localhost awk]$ cat awkscript3
{
if ($1~/Jane/){next}
else {print}
}
9.2 exit函数
使用exit函数终止awk语句,但只暂停记录处理,不略过end语句。exit函数的参数值范围是0-255,根据参数确定终止状态。终止状态变量为0表示正常终止,非0表示非正常终止。
10.数组
10.1 用作数组索引的变量
[qwe@localhost awk]$ awk '{id[NR]=$3};END{for(x = 1;x <= NR;x++)\>print id[x]}' awkdata1
10.2 特殊for循环语句
特殊for循环语句用于以下情况:子脚本为字符串、子脚本非连续数字、for循环语句不能使用而通过关联数组读取。
{
for(数组项目){
print 数组名 [项目]
}
}
10.3 用作数组子脚本的字符串
子脚本包含的变量拥有字符串或常数字符串,常数字符串必须使用双引号(“ ”)。
10.4 用作数组子脚本的字段值
数组中的表达式可用作子脚本,所以字段也可用作子脚本。
for (数组的索引值) 语句
10.5 数组和split函数
awk的内置函数split函数截取保存于词和数组的字符串。
[qwe@localhost awk]$ awk 'BEGIN{ split("7/21/2009",date,"/");delete date[3];print "今天 是"date[3]"年"date[1]"月"date[2]"日"}'
今天是年7月21日
10.6 delete函数
函数清除数组要素。
10.7 多维数组
awk默认不支持多维数组,但提供多维格式相关语法,也就是将索引与字符串进行连接的方法。
11. 命令处理参数
ARGV:awk中名为ARGV的内置数组可用作命令行参数,该参数包含awk命令,但是不能向awk传递任何选项。ARGV数组从0开始。
ARGC:ARGC是内置变量,代表命令行参数的个数。
12.awk内置函数
12.1 字符串函数
sub函数:在记录中检索匹配正则表达式的字符串,并替换为需要的字符串。
sub(正则表达式,需要替换的字符串);
sub (正则表达式,需要替换的字符串,目标字符串)
[qwe@localhost awk]$ awk '{sub(/li/,"HI");print}' awkfile2
hong jitong 3324 5/11/96 50354
HIn kilnit 5246 15/9/66 287650
HI cehnggui 7654 6/20/58 60000
index函数:返回在字符串中首次发现substring的位置。
index(string,substring)
[qwe@localhost awk]$ awk 'BEGIN{ print index("hello","lo")}'
4
length函数:返回字符串中的字符数。
substr函数:从已有字符串截取至指定的开始位置之前的全部内容,然后返回剩余字符串。
substr(字符串,开始位置)
substr(字符串,开始位置,字符串长度)
[qwe@localhost awk]$ awk 'BEGIN{print substr("subta clasus",7,6)}'
clasus
[qwe@localhost awk]$ awk 'BEGIN{print substr("subta clasus",7,3)}'
cla
match函数:返回正则表达式的字符串所在索引位置,查询失败就返回0.
match (字符串,正则表达式)
[qwe@localhost awk]$ awk 'BEGIN{start=match("CentOS LINUX",/[A-Z]+$/);print start}'
8
split函数:使用第三个参数的字段分隔符截取数组的字符串。
split(字符串,数组,字段分隔符)
split(字符串,数组)
sprintf函数:返回指定形式的表达式。
变量=sprintf(“格式指定形式的字符串”,表达式1,表达式2,表达式3)
12.2 数学函数
整数型函数:int函数将指定数据转为整数型。
[qwe@localhost awk]$ awk 'END{print 32/3}' awkfile6
10.6667
[qwe@localhost awk]$ awk 'END{print int(32/3)}' awkfile6
10
rand函数:生成大于0小于1的实数。
srand函数:无参数的函数可使用时间创建srand函数的种子。
[qwe@localhost awk]$ awk 'BEGIN{srand()};{print rand()}' awkfile6
12.3 时间函数
systime函数:返回1970年1月1日至当前时间范围内的时间(精确到秒)。
strftime函数:时间戳,从systime返回。
strftime([format specification][,timestamp])