安全第四天

一、awk

        awk是一种编程语言,用于在linux/unix下对文本和数据进行处理。数据可以来自标准输入(stdin)、一个或多个文件,或其它命令的输出。它支持用户自定义函数和动态正则表达式等先进功能,是linux/unix下的一个强大编程工具。它在命令行中使用,但更多是作为脚本来使用。awk有很多内建的功能,比如数组、函数等,这是它和C语言的相同之处,灵活性是awk最大的优势。    

1.awk语法 

awk` `[options] ``'program'` `var=value ``file``…``awk` `[options] -f programfile var=value ``file``…``awk` `[options] ``'BEGIN{ action;… } pattern{ action;… } END{ action;… }'` `file` `...

2.awk常用命令选项

  • -F fs:fs指定输入分隔符,fs可以是字符串或正则表达式,如-F:

  • -v var=value:赋值一个用户定义变量,将外部变量传递给awk

  • -f scripfile:从脚本文件中读取awk命令

3.awk变量

变量:内置和自定义变量,每个变量前加 -v 命令选项

3.1 内置变量

(1)格式

  • FS输入字段分隔符默认为空白字符

  • OFS输出字段分隔符,默认为空白字符

  • RS :输入记录分隔符,指定输入时的换行符,原换行符仍有效

  • ORS :输出记录分隔符,输出时用指定符号代替换行符

  • NF :字段数量,共有多少字段, $NF引用最后一列,$(NF-1)引用倒数第2列

  • NR行号,后可跟多个文件,第二个文件行号继续从第一个文件最后行号开始

  • FNR :各文件分别计数, 行号,后跟一个文件和NR一样,跟多个文件,第二个文件行号从1开始

  • FILENAME :当前文件名

  • ARGC :命令行参数的个数

  • ARGV :数组,保存的是命令行所给定的各参数,查看参数

演示:

[root@along ~]# cat awkdemo
hello:world
linux:redhat:lalala:hahaha
along:love:youou
[root@along ~]# awk -v FS=':' '{print $1,$2}' awkdemo  #FS指定输入分隔符
hello world
linux redhat
along love
3.2 自定义变量

自定义变量( 区分字符大小写)

(1)-v var=value

① 先定义变量,后执行动作print

[root@along ~]# awk -v name="along" -F: '{print name":"$0}' awkdemo
along:hello:world
along:linux:redhat:lalala:hahaha
along:along:love:you

② 在执行动作print后定义变量

[root@along ~]# awk -F: '{print name":"$0;name="along"}' awkdemo
:hello:world
along:linux:redhat:lalala:hahaha
along:along:love:you

(2)在program 中直接定义

可以把执行的动作放在脚本中,直接调用脚本 -f

[root@along ~]# cat awk.txt
{name="along";print name,$1}
[root@along ~]# awk -F: -f awk.txt awkdemo
along hello
along linux
along along

4.printf命令

比print更强大

4..1 格式

(1)格式化输出

printf` `"FORMAT"``, item1,item2, ...

① 必须指定FORMAT

不会自动换行,需要显式给出换行控制符,\n

③ FORMAT 中需要分别为后面每个item 指定格式符

(2)格式符:与item 一一对应

  • %c: 显示字符的ASCII码

  • %d, %i: 显示十进制整数

  • %e, %E: 显示科学计数法数值

  • %f :显示为浮点数,小数 %5.1f,带整数、小数点、整数共5位,小数1位,不够用空格补上

  • %g, %G :以科学计数法或浮点形式显示数值

  • %s :显示字符串;例:%5s最少5个字符,不够用空格补上,超过5个还继续显示

  • %u :无符号整数

  • %%: 显示% 自身

(3)修饰符:放在%c[/d/e/f...]之间

  • #[.#]:第一个数字控制显示的宽度;第二个# 表示小数点后精度,%5.1f

  • -:左对齐(默认右对齐) %-15s

  • +:显示数值的正负符号 %+d

4.2 演示
[root@along ~]# awk -F: '{print $1,$3}' /etc/passwd
root 0
bin 1
---第一列显示小于20的字符串;第2列显示整数并换行
[root@along ~]# awk -F: '{printf "%20s---%u\n",$1,$3}' /etc/passwd
                root---0
                 bin---1
---使用-进行左对齐;第2列显示浮点数
[root@along ~]# awk -F: '{printf "%-20s---%-10.3f\n",$1,$3}' /etc/passwd
root                ---0.000    
bin                 ---1.000
---使用printf做表格
[root@along ~]# awk -F: 'BEGIN{printf "username            userid\n-----------------------------\n"}{printf "%-20s|%-10.3f|%-10s\n",$1,$3}' /etc/passwd
username            userid
-----------------------------
root                |0.000    
bin                 |1.000

4.5 操作符

4.5.1 格式
  • 算术操作符:

    • x+y, x-y, x*y, x/y, x^y, x%y

    • -x: 转换为负数

    • +x: 转换为数值

  • 字符串操作符:没有符号的操作符,字符串连接

  • 赋值操作符:

    • =, +=, -=, *=, /=, %=, ^=

    • ++a, --a

  • 比较操作符:

    • ==, !=, >, >=, <, <=

  • 模式匹配符:~ :左边是否和右边匹配包含 !~ :是否不匹配

  • 逻辑操作符:与&& ,或|| ,非!

  • 函数调用: function_name(argu1, argu2, ...)

  • 条件表达式(三目表达式):

    selector

    ?

    if-true-expression

    :

    if-false-expression

    • 注释:先判断selector,如果符合执行 ? 后的操作;否则执行 : 后的操作

4.5.2 演示

(1)模式匹配符

---查询以/dev开头的磁盘信息
[root@along ~]# df -h |awk -F: '$0 ~ /^\/dev/'
/dev/mapper/cl-root   17G  7.3G  9.7G  43% /
/dev/sda1           1014M  121M  894M  12% /boot
---只显示磁盘使用状况和磁盘名
[root@along ~]# df -h |awk '$0 ~ /^\/dev/{print $(NF-1)"---"$1}'
43%---/dev/mapper/cl-root
12%---/dev/sda1
---查找磁盘大于40%的
[root@along ~]# df -h |awk '$0 ~ /^\/dev/{print $(NF-1)"---"$1}' |awk -F% '$1 > 40'

(2)逻辑操作符

[root@along ~]# awk -F: '$3>=0 && $3<=1000 {print $1,$3}' /etc/passwd
root 0
bin 1
[root@along ~]# awk -F: '$3==0 || $3>=1000 {print $1}' /etc/passwd
root
[root@along ~]# awk -F: '!($3==0) {print $1}' /etc/passwd
bin
[root@along ~]# awk -F: '!($0 ~ /bash$/) {print $1,$3}' /etc/passwd
bin 1
daemon 2

(3)条件表达式(三目表达式)

[root@along ~]# awk -F: '{$3 >= 1000?usertype="common user":usertype="sysadmin user";print usertype,$1,$3}' /etc/passwd
sysadmin user root 0
common user along 1000

5、awk高阶用法

5.1 awk控制语句—if-else判断

(1)语法

if(condition){statement;…}[else statement]  双分支
if(condition1){statement1}else if(condition2){statement2}else{statement3}  多分支

(2)使用场景:对awk 取得的整行或某个字段做条件判断

(3)演示

[root@along ~]# awk -F: '{if($3>10 && $3<1000)print $1,$3}' /etc/passwd
operator 11
games 1
[root@along ~]# awk -F: '{if($NF=="/bin/bash") print $1,$NF}' /etc/passwd
root /bin/bash
along /bin/bash

5.2 awk控制语句—while循环

(1)语法

while``(condition){statement;…}

注:条件“真”,进入循环;条件“假”, 退出循环

(2)使用场景

  对一行内的多个字段逐一类似处理时使用

  对数组中的各元素逐一处理时使用

(3)演示

5.3 awk控制语句—do-while循环

1)语法

do` `{statement;…}``while``(condition)

意义:无论真假,至少执行一次循环体

(2)计算1+2+3+...+100=5050

[root@along ~]# awk 'BEGIN{sum=0;i=1;do{sum+=i;i++}while(i<=100);print sum}'
5050

5.4 awk控制语句—for循环

(1)语法

for``(expr1;expr2;expr3) {statement;…}

(2)特殊用法:遍历数组中的元素

for``(var ``in` `array) {``for``-body}

(3)演示

---显示每一行的每个单词和其长度
[root@along ~]# awk -F: '{for(i=1;i<=NF;i++) {print$i,length($i)}}' awkdemo
hello 5
world 5
linux 5
redhat 6
lalala 6
hahaha 6
along 5
love 4
you 3

5.5 awk数组

5.5.1 关联数组:array[index-expression]

(1)可使用任意字符串;字符串要使用双引号括起来

(2)如果某数组元素事先不存在,在引用时,awk 会自动创建此元素,并将其值初始化为“空串”

(3)若要判断数组中是否存在某元素,要使用“index in array”格式进行遍历

(4)若要遍历数组中的每个元素,要使用for 循环:for(var in array) {for-body}

5.5.2 演示
[root@along ~]# cat awkdemo2
aaa
bbbb
aaa
123
123
123
---去除重复的行
[root@along ~]# awk '!arr[$0]++' awkdemo2
aaa
bbbb
123

分析:把每行作为下标,第一次进来,相当于print ias...一样结果为空,打印空,!取反结果为1,打印本行,并且++变为不空,下次进来相同的行就是相同的下标,本来上次的值,!取反为空,不打印,++变为不空,所以每次重复进来的行都不打印

(2)数组遍历

awk 关联数组 key=>value 无序

[root@along ~]# awk 'BEGIN{abc["ceo"]="along";abc["coo"]="mayun";abc["cto"]="mahuateng";for(i in abc){print i,abc[i]}}'
coo mayun
ceo along
cto mahuateng

二、awk的经典实战案例

插入几个新字段

在"a b c d"的b后面插入3个字段e f g

echo "a b c d" | awk '{$2=$2" e f g";print}'
格式化空白

移除每行的前缀、后缀空白,并将各部分左对齐。

[root@bogon ~]# vim 2.txt

      aaaa        bbb     ccc
   bbb     aaa ccc
ddd       fff             eee gg hh ii jj

~                                                 
[root@bogon ~]# awk '{$1=$1;print}' 2.txt
aaaa bbb ccc
bbb aaa ccc
ddd fff eee gg hh ii jj

[root@bogon ~]# awk 'BEGIN{OFS="\t"}{$1=$1;print}' 2.txt
aaaa	bbb	ccc
bbb	aaa	ccc
ddd	fff	eee	gg	hh	ii	jj

根据某字段去重

去掉uid=xxx重复的行。

[root@bogon ~]# vim a.txt

2019-01-13_12:00_index?uid=123
2019-01-13_13:00_index?uid=123
2019-01-13_14:00_index?uid=333
2019-01-13_15:00_index?uid=9710
2019-01-14_12:00_index?uid=123
2019-01-14_13:00_index?uid=123
2019-01-15_14:00_index?uid=333
2019-01-16_15:00_index?uid=9710
~                                  
首先利用uid去重,我们需要利用?进行划分,然后将uid=xxx保存在数组中,这是判断重复的依据
然后统计uid出现次数,第一次出现统计,第二次不统计
[root@bogon ~]# awk -F"?" '!arr[$2]++{print}' a.txt
2019-01-13_12:00_index?uid=123
2019-01-13_14:00_index?uid=333
2019-01-13_15:00_index?uid=9710

筛选给定时间范围内的日志

但是awk提供了mktime()函数,它可以将时间转换成epoch时间值。

# 2019-11-10 03:42:40转换成epoch为1970-01-01 00:00:00
$ awk 'BEGIN{print mktime("2019 11 10 03 42 40")}'
1573328560

借此,可以取得日志中的时间字符串部分,再将它们的年、月、日、时、分、秒都取出来,然后放入mktime()构建成对应的epoch值。因为epoch值是数值,所以可以比较大小,从而决定时间的大小。

下面strptime1()实现的是将2019-11-10T03:42:40+08:00格式的字符串转换成epoch值,然后和which_time比较大小即可筛选出精确到秒的日志。

可以利用patsplit来取时间中的数字

access.log文件


[2023-08-03T01:47:20.491Z] [ message] [vmsvc] [653] VMware Tools Version: 12.1.5.39265 (build-20735119)

[2023-08-03T01:47:20.493Z] [ message] [vmsvc] [653] Guest OS details: architecture='X86' bitness='64' distroName='Ubuntu 22.04.2 LTS' distroVersion='22.04' familyName='Linux' kernelVersion='5.19.0-50-generic' prettyName='Ubuntu 22.04.2 LTS'

[2023-08-03T01:47:20.491Z] [ message] [vmsvc] [653] Log caching is enabled with maxCacheEntries=4096.

[2023-08-03T01:47:20.493Z] [ message] [vmsvc] [653] Core dump limit set to -1

[2023-08-03T01:47:20.616Z] [ message] [vmsvc] [653] Cannot load message catalog for domain 'hgfsServer', language 'zh', catalog dir '/usr/share/open-vm-tools'.

[2023-08-03T01:47:20.616Z] [ message] [vmtoolsd] [653] Plugin 'hgfsServer' initialized.

[2023-08-03T01:47:20.616Z] [ message] [vix] [653] QueryVGAuthConfig: vgauth usage is: 1

[2023-08-03T01:47:20.616Z] [ message] [vmsvc] [653] Cannot load message catalog for domain 'vix', language 'zh', catalog dir '/usr/share/open-vm-tools'.

[2023-08-03T01:47:20.616Z] [ message] [vmtoolsd] [653] Plugin 'vix' initialized.

[2023-08-03T01:47:20.616Z] [ message] [vmsvc] [653] Cannot load message catalog for domain 'appInfo', language 'zh', catalog dir '/usr/share/open-vm-tools'.

[2023-08-03T01:47:20.616Z] [ message] [vmtoolsd] [653] Plugin 'appInfo' initialized.

[2023-08-03T01:47:20.616Z] [ message] [vmsvc] [653] Cannot load message catalog for domain 'componentMgr', language 'zh', catalog dir '/usr/share/open-vm-tools'.

[2023-08-03T01:47:20.616Z] [ message] [vmtoolsd] [653] Plugin 'componentMgr' initialized.

[2023-08-03T01:47:20.616Z] [ message] [vmsvc] [653] Cannot load message catalog for domain 'guestInfo', language 'zh', catalog dir '/usr/share/open-vm-tools'.

[2023-08-03T01:47:20.616Z] [ message] [vmtoolsd] [653] Plugin 'guestInfo' initialized.

[2023-08-03T01:47:20.616Z] [ message] [vmsvc] [653] Cannot load message catalog for domain 'powerops', language 'zh', catalog dir '/usr/share/open-vm-tools'.

[2023-08-03T01:47:20.616Z] [ message] [vmtoolsd] [653] Plugin 'powerops' initialized.

[2023-08-03T01:47:20.616Z] [ message] [resolutionCommon] [653] resolutionCheckForKMS: dlopen succeeded.

[2023-08-03T01:47:20.617Z] [ message] [resolutionCommon] [653] resolutionCheckForKMS: System support available for resolutionKMS.

[2023-08-03T01:47:20.617Z] [ message] [vmsvc] [653] Cannot load message catalog for domain 'resolutionKMS', language 'zh', catalog dir '/usr/share/open-vm-tools'.

[2023-08-03T01:47:20.617Z] [ message] [vmtoolsd] [653] Plugin 'resolutionKMS' initialized.

[2023-08-03T01:47:20.618Z] [ message] [vmsvc] [653] Cannot load message catalog for domain 'timeSync', language 'zh', catalog dir '/usr/share/open-vm-tools'.

[2023-08-03T01:47:20.618Z] [ message] [vmtoolsd] [653] Plugin 'timeSync' initialized.

[2023-08-03T01:47:20.618Z] [ message] [vmsvc] [653] Cannot load message catalog for domain 'vmbackup', language 'zh', catalog dir '/usr/share/open-vm-tools'.

[2023-08-03T01:47:20.618Z] [ message] [vmtoolsd] [653] Plugin 'vmbackup' initialized.

[2023-08-03T01:47:20.644Z] [ message] [vix] [653] VixTools_ProcessVixCommand: command 62

[2023-08-03T01:47:22.065Z] [ message] [vix] [653] VixTools_ProcessVixCommand: command 62

[2023-08-03T01:47:22.066Z] [ message] [vix] [653] ToolsDaemonTcloReceiveVixCommand: command 62, additionalError = 17

[2023-08-03T01:47:22.067Z] [ message] [vmsvc] [653] Executing script for state change 'OS_PowerOn'.

[2023-08-03T01:47:22.067Z] [ message] [powerops] [653] Executing script: '/etc/vmware-tools/poweron-vm-default'

[2023-08-03T01:47:24.440Z] [ message] [vmsvc] [653] Script exit code: 0, success = 1

 

创建awk.text

BEGIN{
	which_time = mktime("2023 08 03 07 20 40")
}

{
	match($0,"^.*\\[(.*)\\].*",arr)
	
	tmp_time = strptime1(arr[1])

	if(tmp_time > which_time){print} 
}

function strptime1(str ,arr,Y,M,D,H,m,S){
	patsplit(str,arr,"[0-9]{1,4}")
	Y=arr[1]
	M=arr[2]
	D=arr[3]
	H=arr[4]
	m=arr[5]
	S=arr[6]
	return mktime(sprintf("%s %s %s %s %s %s",Y,M,D,H,m,S))
}

筛选:

[root@bogon ~]# cat access.log | awk '{print $1}' 

[2023-08-03T01:47:20.491Z]

[2023-08-03T01:47:20.493Z]

[2023-08-03T01:47:20.491Z]

[2023-08-03T01:47:20.493Z]

[2023-08-03T01:47:20.616Z]

[2023-08-03T01:47:20.616Z]

[2023-08-03T01:47:20.616Z]

[2023-08-03T01:47:20.616Z]

[2023-08-03T01:47:20.616Z]

[2023-08-03T01:47:20.616Z]

[2023-08-03T01:47:20.616Z]

[2023-08-03T01:47:20.616Z]

[2023-08-03T01:47:20.616Z]

[2023-08-03T01:47:20.616Z]

[2023-08-03T01:47:20.616Z]

[2023-08-03T01:47:20.616Z]

[2023-08-03T01:47:20.616Z]

[2023-08-03T01:47:20.616Z]

[2023-08-03T01:47:20.617Z]

[2023-08-03T01:47:20.617Z]

[2023-08-03T01:47:20.617Z]

[2023-08-03T01:47:20.618Z]

[2023-08-03T01:47:20.618Z]

[2023-08-03T01:47:20.618Z]

[2023-08-03T01:47:20.618Z]

[2023-08-03T01:47:20.644Z]

[2023-08-03T01:47:22.065Z]

[2023-08-03T01:47:22.066Z]

[2023-08-03T01:47:22.067Z]

[2023-08-03T01:47:22.067Z]

[2023-08-03T01:47:24.440Z]

                
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值