一. awk
awk:报告生成器,格式化输出。
在 Linux/UNIX 系统中,awk 是一个功能强大的编辑工具,逐行读取输入文本,默认以空格或tab键作为分隔符作为分隔,并按模式或者条件执行编辑命令。而awk比较倾向于将一行分成多个字段,然后进行处理。
AWK信息的读入也是逐行指定的匹配模式进行查找,对符合条件的内容进行格式化输出或者过滤处理,可以在无交互 的情况下实现相当复杂的文本操作,被广泛应用于 Shell 脚本,完成各种自动化配置任务。
其中awk有多种版本:
- AWK
- NAWK
- GAWK(目前使用)
gawk、vim和awk的区别
gawk:模式扫描和处理语言,可以实现下面功能
vim:是将整个文件加载到内存中在加载到你的内存中,但这取决于你的内存文件是否能够容纳文本文件的大小。
awk(语言):读取一行,处理一行
工作模式:
sed命令常用于一整行的处理,而awk比较倾向于一整行的分成多个字段处理,默认情况下字段的分隔符为空格或tab键。awk执行结果可以通过print的功能将字段数据打印出来。
格式:awk [options] 'program' var=value file…
解释说明:
program是被放在单引号中,通常由三个部分组成:
- BEGIN语句块
- 模式匹配的通用语句块
- END语句块
常用选项 | 功能 |
---|---|
-F | 分隔符指明输入时用到的字符分隔符,默认的字符分隔符是若干个连续的空白符 |
-v | var=value变量赋值 |
program格式:xxxxxxxxxx1 11 1pattern{action statements;..}
pattern:决定动作语句何时触发及触发事件。比如:BEGIN、END、正则表达式等
action statements(行为语句):对数据进行处理 ,放在{}内指明。常见的是:print、printf
- output statement(输出语句):print、printf
- expressions(表达式):算术表达式、比较表达式等
- compound statement(组合语句)
- control statement(控制语句):if语句、for、while等
- input statement(输入语句)
执行过程
第一步:执行BEGIN{action;… }语句块中的语句
第二步:从文件或标准输入(stdin)读取一行,然后执行pattern{ action;… }语句块,它逐行扫描文件,
从第一行到最后一行重复这个过程,直到文件全部被读取完毕。
第三步:当读至输入流末尾时,执行END{action;…}语句块解释:
BEGIN语句块在awk开始从输入流中读取行之前被执行,这是一个可选的语句块,比如变量初始化、打印输出表格的表头等语句通常可以写在BEGIN语句块中
END语句块在awk从输入流中读取完所有的行之后即被执行,比如打印所有行的分析结果这类信息汇总都是在END语句块中完成,它也是一个可选语句块
pattern语句块中的通用命令是最重要的部分,也是可选的。如果没有提供pattern语句块,则默认执行{ print },即打印每一个读取到的行,awk读取的每一行都会执行该语句块
1.1 基本动作
print动作
1.2 BEGIN
取出已用项--方法一
取出已用项--方法二
取出已用项--方法三
BEGIN{}模式表示,在处理指定的文本前,需要先执行BEGIN模式中的指定动作; awk再处理指定的文本,之后再执行END模式中的指定动作,END{}语句中,一般会放入打印结果等语句。
1.3 常见的内置变量
格式:awk 选项 '模式{print }'
选项 | 功能 |
---|---|
FS | 指定每段的字段分隔符,缺省默认认为空格或制表符,与 “-F”作用相同 -v "FS=:" |
OFS | 输出时的分隔符 |
NF | 当前处理的行的字段个数 |
NR | 当前处理的行的行数(序数) |
$0 | 当前处理的行的整个内容 |
$n | 当前处理行的第n个字段(第n列) |
FILENAME | 被处理的文件名 |
RS | 行分隔符。awk从文件上读取资料时,将根据RS的定义就把资料切割成许多条记录,而awk一次仅读入一条记录进行处理 |
FS
支持变量
-F和-FS一起使用,-F的优先级更高
OFS
RS
默认是已 /n (换行符)为一条记录的分隔符
FS
代表字段的个数
$NF代表最后一个字段
打印倒数第二列
打印已用项
NR
行号
FNR
FILENAME
显示处理文件名
1.4 模式PATTERN
格式:awk '模式{处理动作}'
PATTERN:根据pattern条件,过滤匹配的行,再做处理
1.4.1 模式为空
如果模式为空表示每一行都匹配成功,相当于没有额外条件
1.4.2 正则匹配
/regular expression/:仅处理能够模式匹配到的行,需要用/ /括起来。举例:awk '/^UUID/{print $1}' /etc/fstab
1.4.3 line range:行范围
不支持使用行号,但是可以使用变量NR 间接指定行号加上比较操作符 或者逻辑关系
算术操作符
x+y, x-y, x*y, x/y, x^y, x%y
-x:转换为负数
+x:将字符串转换为数值
比较操作符:
==, !=, >, >=, <, <=
逻辑
与:&&,并且关系
或:||,或者关系
非:!,取反关系
1.4.4 找到10:00到11:00之间的日志
awk '/10/,/11/' 文件名
sed -nr '/10/,/11/p' 文件名
1.4.5 BEGIN END
BEGIN{}:仅在开始处理文件中的文本之前执行一次
END{}:仅在文本处理完成之后执行一次
1.4.6 关系表达式
关系表达式结果为“真”才会被处理
真:结果为非0值,非空字符串
假:结果为空字符串或0值
1.5 条件判断(扩展)
格式:awk 选项 '模式 {actions}'
条件判断写在 actions里
if(condition){statement;…}[else statement]
if(condition1){statement1}else if(condition2){statement2}else if(condition3){statement3}...... else {statementN}condition1:条件
statement1:语句if语句:awk的if语句也分为单分支、双分支和多分支
单分支为if(判断条件){执行语句}
双分支为if(判断条件){执行语句}else{执行语句}
多分支为if(判断条件){执行语句}else if(判断条件){执行语句}else if(判断条件){执行语句}else if(判断条件){执行语句}
1.6 for | while
语法:
for(expr1;expr2;expr3) {statement;…}
for(variable assignment;condition;iteration process) {for-body}
for(var in array) {for-body}
1.7 数组(awk数组)
awk数组特性:
- awk的数组是关联数组(即key/value方式的hash数据结构),索引下标可为数值(甚至是负数、小数等),也可为字符串
- 在内部,awk数组的索引全都是字符串,即使是数值索引在使用时内部也会转换成字符串
- awk的数组元素的顺序和元素插入时的顺序很可能是不相同的
- awk数组支持数组的数组
1.7.1 数组长度
awk提供了 length() 函数来获取数组的元素个数,它也可以用于获取字符串的字符数量。还可以获取数值转换成字符串后的字符数量。
1.7.2 遍历数组
格式:for(var in array) {for-body}
1.8 脚本
将awk程序写成脚本,直接调用或执行
1.9 彩蛋
1.9.1.提出下面的IP地址和字段
awk
58.87.87.99 - - [09/Jun/2020:03:42:43 +0800] "POST /wp-cron.php?doing_wp_cron=1591645363.2316548824310302734375 HTTP/1.1" ""sendfileon
128.14.209.154 - - [09/Jun/2020:03:42:43 +0800] "GET / HTTP/1.1" ""sendfileon
64.90.40.100 - - [09/Jun/2020:03:43:11 +0800] "GET /wp-login.php HTTP/1.1"""sendfileo64.90.40.100 09/Jun/2020:03:43:11
解法1:cat test|sed -nr 's/(.*) - - \[(.*) \+.*/\1 \2/p'
解法2:cat test|awk -F"[[]" '{print $1,$5}'
解法3:cat test|awk -F"[[]+" '{print $1,$4}'
1.9.2.提取host.txt主机名后再放回host.txt文件 >>
vim host.txt
1 www.kgc.com
2 mail.kgc.com
3 ftp.kgc.com
4 linux.kgc.com
5 blog.kgc.com解法1:cat host.txt awk -F"[ .]" 'print $2' >>host.txt
解法2:cat host.txt | cut -d "." -f1|tr -d "[0-9 ]">>host.txt
解法3:cat host.txt | sed -nr 's/[0-9](.*)\.kgc\.com/\1/p'>>host.txt
1.9.3.统计/etc/fstab文件中每个文件系统类型出现的次数
cat /etc/fstab | grep -v "^#"|grep -v "^$"|awk '{print $3}' sort|uniq -c
1.9.4.统计/etc/fstab文件中每个真单词出现的次数
解法1:cat /etc/fstab | grep -Eo "\b[a-zA-Z]+\b" |wc -l
解法2:cat /etc/fstab | grep -Eo "\b[[:alpha:]]\b" |wc -l
1.9.5.提取出字符串Yd$C@M05MB%9&Bdh7dq+YVixp3vpw中的所有数字
echo "Yd$C@M05MB%9&Bdh7dq+YVixp3vpw" | grep -o [0-9]
1.9.6.查出/tmp/的权限,以数字方式显示
stat /tmp|awk -F "[(/]" 'NR=4{print $2}'
1.9.7.查出用户UID最大值的用户名、UID及shell类型
awk $3>1000{print $3,$1} /etc/passwd |sort -n |uniq -c