Linux(Centos 7.6)命令详解:awk

1.命令作用

模式扫描和处理语言(pattern scanning and processing language);awk是一种编程语言,用于在linux/unix下对文本和数据进行处理,本质是对满足条件的行数据进行处理(也可以处理其中某个列,或者某几个列)

2.命令语法

Usage: awk [POSIX or GNU style options] -f progfile [--] file ...
Usage: awk [POSIX or GNU style options] [--] 'program' file ...

3.参数详解

OPTIONS:

POSIX options: , GNU long options: (standard)

  • -f progfile, --file=progfile,从文本中加载脚本
  • -F fs, --field-separator=fs,字段/域分隔符
  • -v var=val, --assign=var=val,自定义变量

Short options: , GNU long options: (extensions)

  • -b, --characters-as-bytes,以字节数方式处理,如统计行字符数时,-b对中文处理明显不通
  • -c, --traditional,
  • -C, --copyright,打印版权信息
  • -d[file], --dump-variables[=file],执行过程中使用的‌全局变量‌(包括内置变量和用户定义变量)导出到指定文件中
  • -e 'program-text', --source='program-text',指定多个指令执行
  • -E file, --exec=file,与 -f 类似,但具有更强的安全性和隔离性
  • -g, --gen-pot,
  • -h, --help,打印帮助信息
  • -L [fatal], --lint[=fatal]
  • -n, --non-decimal-data,awk默认情况下,0x开头的是16进制,0开头的是8进制,-n无效果,如awk 'BEGIN{print 0x123}'
  • -N, --use-lc-numeric
  • -O, --optimize,启动内部优化机制
  • -p[file], --profile[=file],将执行内容输出到文件,后续可直接使用awk -f file执行,如不指定文件名称,则输出到awkprof.out
  • -P, --posix,以posix标准模式运行
  • -r, --re-interval,启用正则表达式中的区间表达式{m,n}支持
  • -S, --sandbox,启用沙盒模式,正常模式下允许文件操作,沙盒模式下文件操作会报错
  • -t, --lint-old,检测脚本中的兼容性问题
  • -V, --version,打印版本信息

4.参数用例

4.1.指定awk脚本文件执行,对某列进行求和

[root@node1 ~]# free | grep -v total
Mem:        3861520      462908     2942300       15712      456312     3080864
Swap:       4064252           0     4064252
[root@node1 ~]# cat calc.awk 
BEGIN { sum=0 }
{ sum+=$2 }
END { print "总和:", sum }
[root@node1 ~]# free | grep -v total | awk -f calc.awk 
总和: 7925772
[root@node1 ~]# 
[root@node1 ~]# free | grep -v total | awk -E calc.awk 
总和: 7925772
[root@node1 ~]# 

4.2.自定义分隔符,默认为空格或者tab

[root@node1 ~]# cat test.txt 
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
adm:x:3:4:adm:/var/adm:/sbin/nologin
lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
sync:x:5:0:sync:/sbin:/bin/sync
[root@node1 ~]# 
[root@node1 ~]# awk -F':' '{print $1}' test.txt 
root
bin
daemon
adm
lp
sync
[root@node1 ~]# 

 4.3.自定义变量

[root@node1 ~]# awk -F ':' -v n=10 '{print $3+n}' test.txt  # 打印文件中第三列加上变量n的结果
10
11
12
13
14
15
[root@node1 ~]# 

4.4.以字节数进行处理,中文处理时默认时字符数统计,添加-b以字节数进行处理

[root@node1 ~]# cat test1.txt 
好好学习天天向上
this is a cat;
[root@node1 ~]# awk -b '{print length($0)}' test1.txt 
24
14
[root@node1 ~]# awk '{print length($0)}' test1.txt 
8
14
[root@node1 ~]# 

 4.5.执行变量‌导出到指定文件中

[root@node1 ~]# awk -ddump.txt -F ':' '{sum+=$3} END{print sum}' test.txt   
15
[root@node1 ~]# cat dump.txt 
ARGC: 2
ARGIND: 1
ARGV: array, 2 elements
BINMODE: 0
CONVFMT: "%.6g"
ERRNO: ""
FIELDWIDTHS: ""
FILENAME: "test.txt"
FNR: 6
FPAT: "[^[:space:]]+"
FS: ":"
IGNORECASE: 0
LINT: 0
NF: 7
NR: 6
OFMT: "%.6g"
OFS: " "
ORS: "\n"
RLENGTH: 0
RS: "\n"
RSTART: 0
RT: "\n"
SUBSEP: "\034"
TEXTDOMAIN: "messages"
sum: 15
[root@node1 ~]# 

 4.6.指定多个可执行命令

[root@node1 ~]# awk -F ':' -e 'BEGIN{print "Start"}' -e '{print $3}' test.txt    # 先打印 "Start",再输出 data.txt 每行的第一列
Start
0
1
2
3
4
5
[root@node1 ~]# 
[root@node1 ~]# awk -F ':' -e '{print $1}' -e '{print $3}' test.txt  # 打印多个列交叉输出
root
0
bin
1
daemon
2
adm
3
lp
4
sync
5
[root@node1 ~]# 
[root@node1 ~]# awk --source='BEGIN{FS=":"}' --source='{print $5}' test.txt 
root
bin
daemon
adm
lp
sync
[root@node1 ~]# 

4.7.启动awk内部优化

[root@node1 ~]# cat test2.txt 
123
456
789
101
112
131
415
[root@node1 ~]# time awk '{for(i=1;i<=10000000;i++) sum+=$1} END{print sum}' test2.txt   # 未优化
21270000000

real	0m9.824s
user	0m9.812s
sys	0m0.011s
[root@node1 ~]# time awk -O '{for(i=1;i<=10000000;i++) sum+=$1} END{print sum}' test2.txt  # 启动优化
21270000000

real	0m9.683s
user	0m9.676s
sys	0m0.006s
[root@node1 ~]#

 4.8.将执行内容输出到文件,后续可直接使用awk -f file执行

[root@node1 ~]# awk --profile 'BEGIN{for(i=1;i<=1000;i++) print i}'  # 将awk执行内容输出到文件,不指定文件名称默认输出到awkprof.out
1
... ...
1000
[root@node1 ~]# cat awkprof.out 
	# gawk profile, created Fri Jun  6 03:26:51 2025

	# BEGIN block(s)

	BEGIN {
		for (i = 1; i <= 1000; i++) {
			print i
		}
	}

[root@node1 ~]# awk --profile=awkprof.awk 'BEGIN{for(i=1;i<=1000;i++) print i}'  # 指定输出文件

4.9.以posix标准模式运行

[root@node1 ~]# awk 'BEGIN{print 2**3}'
8
[root@node1 ~]# awk --posix 'BEGIN{print 2^3}'
8
[root@node1 ~]# awk 'BEGIN{print 2^3}'
8
[root@node1 ~]# awk --posix 'BEGIN{print 2**3}'
awk: cmd. line:1: BEGIN{print 2**3}
awk: cmd. line:1:               ^ syntax error
[root@node1 ~]# 

 4.10.启用正则表达式中的区间表达式{m,n}支持

[root@node1 ~]# cat test3.txt 
this is a cat
is good
Never give up
gooood
good
gived
uping
going
[root@node1 ~]# awk '/go{2,5}d/{print}'  test3.txt 
is good
gooood
good
[root@node1 ~]# awk -r '/go{2,5}d/{print}'  test3.txt 
is good
gooood
good
[root@node1 ~]# 

4.11.启用沙盒模式,正常模式下允许文件操作,沙盒模式下文件操作会报错

[root@node1 ~]# awk '{print $0 > "output.txt"}' test.txt 
[root@node1 ~]# cat output.txt 
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
adm:x:3:4:adm:/var/adm:/sbin/nologin
lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
sync:x:5:0:sync:/sbin:/bin/sync
[root@node1 ~]# awk -S '{print $0 > "output1.txt"}' test.txt 
awk: cmd. line:1: (FILENAME=test.txt FNR=1) fatal: redirection not allowed in sandbox mode
[root@node1 ~]# 

5.其他用例

5.1.打印出第3列

[root@node1 ~]# ps aux | awk '{print $3}' | head -n 5
%CPU
0.0
0.0
0.0
0.0
[root@node1 ~]# 

5.2.按照':'作为分隔符,打印第2,第3列

[root@node1 ~]# awk -F ':' '{print $2,$3}' test.txt
x 0
x 1
x 2
x 3
x 4
x 5
[root@node1 ~]#

5.3.打印最后一列,打印总列数

# NF 是列的数量,$NF即为最后一行,该文件:分隔共7列,$NF与$7效果一样
# NF: number of filed
[root@node1 ~]# awk -F ':' '{print $NF}' test.txt  
/bin/bash
/sbin/nologin
/sbin/nologin
/sbin/nologin
/sbin/nologin
/bin/sync
[root@node1 ~]# 
[root@node1 ~]# awk -F ':' '{print NF}' test.txt | tail -n1 # 打印总列数
7
[root@node1 ~]# 

5.4.打印指定行第5行,打印总行数

# NR: number of row
[root@node1 ~]# awk '{if(NR==5) print}' test.txt       # 打印第5行
lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
[root@node1 ~]# 
[root@node1 ~]# awk '{print NR}' test.txt | tail -n 1  # 打印行数
6
[root@node1 ~]# 

5.5.指定分隔符,打印第2、3、4列,打印的列分隔符与原分隔符一样

# OFS: output field separator,输出的分隔符,不指定默认为空格
# FS: field separator,即-F指定的内容
# OFS=FS: 即输出的分隔符为-F指定的内容
[root@node1 ~]# awk -F ':' '{OFS=FS; print $2,$3,$4}' test.txt
x:0:0
x:1:1
x:2:2
x:3:4
x:4:7
x:5:0
[root@node1 ~]# 

5.6.指定分隔符,将第2列全部改xxxx字符串

[root@node1 ~]# awk -F ':' '{OFS=FS;$2="xxxx";print}' test.txt 
root:xxxx:0:0:root:/root:/bin/bash
bin:xxxx:1:1:bin:/bin:/sbin/nologin
daemon:xxxx:2:2:daemon:/sbin:/sbin/nologin
adm:xxxx:3:4:adm:/var/adm:/sbin/nologin
lp:xxxx:4:7:lp:/var/spool/lpd:/sbin/nologin
sync:xxxx:5:0:sync:/sbin:/bin/sync
[root@node1 ~]# 

5.7.指定分隔符,将第2-4行的第2列改成xxxx

[root@node1 ~]# awk -F ':' '{if(NR >=2 && NR <=4) $2="xxxx";OFS=FS;print}' test.txt 
root:x:0:0:root:/root:/bin/bash
bin:xxxx:1:1:bin:/bin:/sbin/nologin
daemon:xxxx:2:2:daemon:/sbin:/sbin/nologin
adm:xxxx:3:4:adm:/var/adm:/sbin/nologin
lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
sync:x:5:0:sync:/sbin:/bin/sync
[root@node1 ~]# 

5.8.指定分隔符,打印第7列匹配'bash'关键字的行

# 匹配为~ ,不匹配为!~
[root@node1 ~]# awk -F ':' '{if($7 ~ /bash/) print}' test.txt
root:x:0:0:root:/root:/bin/bash
[root@node1 ~]# 

5.9.打印第一列,且每行前添加指定字符

[root@node1 ~]# awk -F ':' -v 'a=xx' '{print a,$1}' test.txt 
xx root
xx bin
xx daemon
xx adm
xx lp
xx sync
[root@node1 ~]# 

5.10.指定分隔符,取出第7列中第4个字符开始往后取5个字符

[root@node1 ~]# awk -F ':' '{print substr($7,4,5)}' test.txt 
n/bas
in/no
in/no
in/no
in/no
n/syn
[root@node1 ~]# 

5.11.指定分隔符,替换第7列中的sbin为TTTT

推广至满足某些条件的行当中的某些列进行处理;

注:awk中字符串等请使用双引号;

[root@node1 ~]# awk -F ':' '$7 ~ /sbin/ {OFS=FS;gsub("sbin","TTTT",$7);print}' test.txt 
bin:x:1:1:bin:/bin:/TTTT/nologin
daemon:x:2:2:daemon:/sbin:/TTTT/nologin
adm:x:3:4:adm:/var/adm:/TTTT/nologin
lp:x:4:7:lp:/var/spool/lpd:/TTTT/nologin
[root@node1 ~]# 

5.12.取出日志中时间在2024年9月11日10点0分到10点10分的日志

# 日期后面是' CST',以此为分隔符,$1则为时间列
awk -F ' CST' '{if ($1 >= "2024-09-11 10:00:00" && $1 <= "2024-09-11 10:10:00") print}' test.csv

# sed -n '/开始时间/,/结束时间/p' xxx.log
# 注:必须保证匹配的"开始时间"和"结束时间"内容在日志文件中都存在,如果不存在,将取不到数据
sed -n '/2024-09-11 10:00:00/,/2024-09-11 10:10:00/p' test.csv 

5.13.将第2到5行数据的第3列求和

[root@node1 ~]# awk -F ':' 'BEGIN {sum=0} {if(NR>=2 && NR<=4) sum=sum+$3} END {print sum}' test.txt
6
[root@node1 ~]# 

注:不管有没有BEGIN或者END,书写格式中都需要有{}作为前后结尾;但如果是匹配,则略有不同:
[root@node1 ~]# awk -F ':' '$7 ~ /sbin/ {OFS=FS;gsub("sbin","TTTT",$7);print}' test.txt 
bin:x:1:1:bin:/bin:/TTTT/nologin
daemon:x:2:2:daemon:/sbin:/TTTT/nologin
adm:x:3:4:adm:/var/adm:/TTTT/nologin
lp:x:4:7:lp:/var/spool/lpd:/TTTT/nologin
[root@node1 ~]# awk -F ':' '{if($7 ~ /sbin/) {OFS=FS;gsub("sbin","TTTT",$7);print}}' test.txt 
bin:x:1:1:bin:/bin:/TTTT/nologin
daemon:x:2:2:daemon:/sbin:/TTTT/nologin
adm:x:3:4:adm:/var/adm:/TTTT/nologin
lp:x:4:7:lp:/var/spool/lpd:/TTTT/nologin
[root@node1 ~]# 

5.14.用户下cpu内存使用量

1)ps aux | awk 'BEGIN {cpusum=0;memsum=0} $1 ~/clouder|hdfs/ {cpusum=cpusum+$3; memsum=memsum+$4}; END {print cpusum,memsum}'
2)cpusum=0;for i in `ps aux | awk ‘$1 ~/clouder|hdfs/ {print $3}’`; do cpusum=$(($cpusum+$i)) ;done;echo $cpusum  (注:shell中浮点数相加不能直接$(($cpusum+$i)),需要另寻办法) 
3)a=0;for i in `ps aux | awk '$1 ~/clouder|hdfs/ {print $3}'`; do a=`echo "$a+$i"|bc` ;done;echo $a

5.15.Length字符串函数的使用

5.15.1.打印出每行的总长度

[root@node1 ~]# awk '{print length}' test.txt 
31
32
39
36
40
31
[root@node1 ~]# 

5.15.2.打印出第7列长度

[root@node1 ~]# awk -F ':' '{print length($7)}' test.txt 
9
13
13
13
13
9
[root@node1 ~]# 

5.15.3.打印所有列,且统计每行总长度

[root@node1 ~]# awk -F ':' '{print($0),length}' test.txt 
root:x:0:0:root:/root:/bin/bash 31
bin:x:1:1:bin:/bin:/sbin/nologin 32
daemon:x:2:2:daemon:/sbin:/sbin/nologin 39
adm:x:3:4:adm:/var/adm:/sbin/nologin 36
lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin 40
sync:x:5:0:sync:/sbin:/bin/sync 31
[root@node1 ~]# 

5.15.4.打印第二列,且统计第二列的长度

[root@node1 ~]# awk -F ':' '{print($5),length($5)}' test.txt 
root 4
bin 3
daemon 6
adm 3
lp 2
sync 4
[root@node1 ~]# 

5.16.其他

# 开始定义sum=0
# $1第一列不存在#号的行,计算第二列的和
# 当和大于86时,输出第一列,求和,然后将sum置为0
# 依次循环处理
# 可以考虑最后sum不满86,是不是会不输出,可以生成数字进行测试
awk 'BEGIN {sum = 0}; $1 !~ /#/ {sum=sum+$2;if (sum >86) {print $1,sum;sum=0 }}' text.log

text.log内容如
# this is number one
1 12
2 23
3 22
4 8
5 7
6 14
. .
. .
. .
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

豆是浪个

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值