linux 三剑客之awk

时间:2024-07-27 18:05:38

AWK命令


基础显示

打印install.log文件中包含data字段行的第二区域

awk ‘/data/ {print $2}’ install.log

查看num10.txt的第一行

head -n 1 num10.txt
结果:10 cat !$ #cat上次打开的文件,cat num10.txt

awk只显示第一行:

NR number of row 第几行

AWK读取文件是一行一行读取;

awk 'NR==1' num10.txt
结果:10

awk打印最后一行:

awk 'END{print $0}' num10.txt
结果: 1 最后一行

显示最后一列:

NF number of fields 列

awk -F ' ' '{print $NF}' qqq
结果:
lll
222

不显示第一行

awk 'NR != 1' num10.txt

不显示最后一列

awk -F ' ' 'BEGIN{OFS="---"}{print $1,$2,$3}' qqq
结果:
123---123---c
1fsda---ddd3---222

ORS,默认每一行结束之后是换行符

awk -F " " 'BEGIN{OFS="";ORS=""}{for(i = 1;i < NF; i++){print $i" "}{printf "\n"}}' qqq
123 123 c
1fsda ddd3 222

基础运算

突然想起用python解决,来两个实例~

现在有文件qqq,内容如下:

1 2 3 4 5

2 3 4 5 6

3 4 5 6 7

实例1:(求每行的和)
with open("qqq") as f:
j = 0
for line in f: # line 是字符串数据类型。
li = line.strip().split() # split生成列表数据
sum = 0
for i in li:
sum += int(i)
# print(line,sum)
j += 1
print(j,sum)
结果:
1 15
2 20
3 25 实例2:(求所有值的和)
with open("qqq") as f:
sum = 0
for line in f: # line 是字符串数据类型。
li = line.strip().split() #split生成列表数据
for i in li:
sum += int(i)
print(sum)
结果:
60

字符匹配

现在有文件grade,内容如下:

john 10 3  78 94 88
andrea 20 90 75 90 86
jasper 90 450 90 92 84
sun 60 50 80 98 87

打印第一列为sun的行

awk  '{if($1 == "sun")print $0}' grade
结果:
sun 60 50 80 98 87

打印第一列长度大于4,第二列大于40的行。

awk '{if (length($1) > 4 && $2 > 40) print $0}' grade
jasper 90 450 90 92 84 awk 不指定-F,就是默认空格或者table来分割。

正则匹配: ~

awk  '{if($1 ~ "su")print $0}' grade
结果:
sun 60 50 80 98 87 11. 匹配noarch字段,如果有,则显示整行
$awk ‘$2 ~ /noarch/’ install.log
12. 匹配不存在noarch字段的行,如果有,
则显示整行
$awk ‘$2 !~ /noarch/’ install.log

流程控制

两个单引号之间可以有多个{},if语句示例如下

示例1: /etc/passwd 把root改成admin,别的是common user的列表。

awk -F: '{
if ($1 == "root")
printf "%-15s: %s\n", $1,"Admin"
else
print "%-15s: %s\n", $1,"Common User"
}' /etc/passwd

示例2:有多少个普通用户,UID > 1000

awk -F: -v sum=0 '{    # sum=0  这里不能有空格
if ($3 > 1000)
sum++
}END{
print sum
}' /etc/passwd
结果:
47

流程如下、

if流程

If
'{if(条件){action}}'

for 流程

for
'{for (条件) {action}}'

练习:打印最后一列小于等于6的所有行/他的值(还是用python吧。。。。)

with open("qqq") as f:
for line in f:
print(line.strip(),type(line.strip())) # line in f 中 line 是字符串,strip()去掉换行符。
li = line.strip().split()
a = int(li[-1])
if a > 6:
pass
# print(line)
# print(a)
else:
pass
结果:
1 2 3 4 5 <class 'str'>
2 3 4 5 6 <class 'str'>
3 4 5 6 7 <class 'str'> awk '{if ($NF <= 6) print $0}' qqq #AWK一条命令解决



AWK命令格式

awk 指令是由模式,动作,或者模式和动作的组合组成。

'pattern {action}'

pattern 即模式,也可以理解为条件,你要找谁,高矮,胖瘦,等,都是条件。
action:即动作,可以理解为干啥,找到人之后你要干嘛

AWK执行过程

a) awk屈辱第一行内容
b) 判断是否符合模式中得条件,匹配则执行action,不匹配,继续读取下一行
c) 继续读取下一行
d) 直到读取到最后一行(EOF end of file)

域与记录详解

field 域,区域,字段 $1,$2等,表示第一个字段,第二个字段等。

record 记录,可以理解为一整行

内置变量:
RS == record seperator 即行得分隔符
NR == number of record 行号
ORS == output record seperator 输出时候得分隔符

awk得正则匹配

^cool 匹配所有以cool开头得字符串
cool$ 匹配所有以cool结尾得字符串
a+b 匹配一个或多个a 加上b得行 ifconfig eth0 |awk -F "[ :]+" 'NR==2 {print $3 }'
ifconfig eth0 | awk -F "netmask|broadcast" 'NR==2{print $3}' 怎么匹配1,不匹配到11:
awk --posix -F: '$3~/1{2,}/{print $0}' test.awk 出现两次得可以出来,写成{1,} 也还是都出来了 awk -F: '$3~/\<1\>/{print $0}' test.awk
\< 或 \b:词首锚定;用于单词模式的左侧;
\> 或 \b:词尾锚定;用于单词模式的右侧;
\<PATTERN\>:匹配整个单词; netstat -lantp | awk -F "[:/ ]+" '{print $5,"\t",$10}'| sort 查询服务得端口

BEGIN和END模块详解

找空行:
grep -c '^$' test.awk
awk -v a=0 '/^$/{a=a+1}END{print a}' test.awk awk -v a=0 -F: '$3>=5{a=a+1;(用;号分割)print a(a++)}END{print a}' test.awk