jck28-lucio-linux三剑客之awk

主要用作数据分段处理(默认空白分隔)

awk 基本语法

  • awk 是 linux 下的一个命令,同时也是一种语言解析引擎
  • awk 具备完整的编程特性。比如执行命令,网络请求等
  • 精通 awk,是一个 linux 工作者的必备技能
  • 语法 awk 'pattern{action}'

awk 上下文变量

  • 开始 BEGIN 结束 END
  • 行数 NR
  • 字段与字段数 $1 $2 … $NF NF
  • 整行 $0
  • 字段分隔符 FS
  • 输出数据的字段分隔符 OFS
  • 记录分隔符 RS
  • 输出字段的行分隔符 ORS

字段变量用法

  • -F 参数指定字段分隔符,可以用|指定多个- 多分隔符 -F ‘<|>’
  • BEGIN{FS=“_”} 也可以表示分隔符
  • $0 代表当前的记录
  • $1 代表第一个字段
  • $N 代表第 N 个字段
  • $NF 代表最后一个字段
  • $(NF-1) 代表倒数第二个字段

pattern 表达式

  • 正则匹配 $1~/pattern/ /pattern/
  • 比较表达式 $2>2 $1=="b"

awk pattern 匹配表达式案例

  • 开始和结束 awk 'BEGIN{}END{}'
  • 正则匹配
    • 整行匹配 awk '/Running/'
    • 字段匹配 awk '$2~/xxx/'
  • 行数表达式
    • 取第二行 awk 'NR==2'
    • 去掉第一行 awk 'NR>1'
  • 区间选择
    • awk '/aa/,/bb/'
    • awk '/1/,NR==2'

[jck287213@shell.ceshiren.com ~]$ echo '1

2
3’
1
2
3
[jck287213@shell.ceshiren.com ~]$ echo ‘1
2
3’ | awk ‘NR==1’(取第一行)
1
[jck287213@shell.ceshiren.com ~]$ echo ‘1
2
3’ | awk ‘NR==2’(取第二行)
2
[jck287213@shell.ceshiren.com ~]$ echo ‘1
2
3’ | awk ‘$1~/2/’(第1字段匹配2)
2
[jck287213@shell.ceshiren.com ~]$ echo ‘1
2
3’ | awk ‘/2/’(整行匹配2))
2

[jck287213@shell.ceshiren.com test]$ head -n 5 uniq_demo.txt
ck141906 pts/0 120.52.147.49
ck140081 pts/13 113.65.231.23
ck140081 pts/12 113.65.231.23
ck140081 pts/4 221.219.101.182
82894931 pts/12 36.112.85.179
[jck287213@shell.ceshiren.com test]$ head -n 5 uniq_demo.txt | awk ‘NR==1,NR==3{print $0}’( 1. #打印1-3行的行内容
ck141906 pts/0 120.52.147.49
ck140081 pts/13 113.65.231.23
ck140081 pts/12 113.65.231.23
[jck287213@shell.ceshiren.com test]$ head -n 5 uniq_demo.txt | awk ‘(NR>=1)&&(NR<=3){print $0}’( 1. #打印1-3行的行内容,&&表示“与”)
ck141906 pts/0 120.52.147.49
ck140081 pts/13 113.65.231.23
ck140081 pts/12 113.65.231.23
[jck287213@shell.ceshiren.com test]$ head -n 5 uniq_demo.txt | awk ‘(NR==1)||(NR==3){print $0}’ ( 1. #打印第1行或第3行的行内容,|| 表示“或”)
ck141906 pts/0 120.52.147.49
ck140081 pts/12 113.65.231.23
[jck287213@shell.ceshiren.com test]$ head -n 5 uniq_demo.txt | awk ‘NR>4{print $0}’( 1. #打印行号大于4的行内容
82894931 pts/12 36.112.85.179
[jck287213@shell.ceshiren.com test]$ head -n 5 uniq_demo.txt | awk ‘!(NR>4){print $0}’( 1. #打印行号小于4的行内容,!表示取反)
ck141906 pts/0 120.52.147.49
ck140081 pts/13 113.65.231.23
ck140081 pts/12 113.65.231.23
ck140081 pts/4 221.219.101.182
[jck287213@shell.ceshiren.com test]$ head -n 5 uniq_demo.txt | awk ‘(NR%2)==1{print $0}’(输出奇数行)
ck141906 pts/0 120.52.147.49
ck140081 pts/12 113.65.231.23
82894931 pts/12 36.112.85.179
[jck287213@shell.ceshiren.com test]$ head -n 5 uniq_demo.txt | awk ‘(NR%2)==0{print $0}’(输出偶数行)
ck140081 pts/13 113.65.231.23
ck140081 pts/4 221.219.101.182
[jck287213@shell.ceshiren.com test]$ head -n 5 uniq_demo.txt | awk ‘/^ck141/{print $0}’(输出以ck141开头的内容)
ck141906 pts/0 120.52.147.49
[jck287213@shell.ceshiren.com test]$ head -n 5 uniq_demo.txt | awk ‘/182$/{print $0}’(输出以182结尾的内容)
ck140081 pts/4 221.219.101.182
[jck287213@shell.ceshiren.com test]$ echo ‘a 1
b 2
c 3’ | awk ‘/a/,/c/’(输出以a开头以c结尾之间的行的数据)
a 1
b 2
c 3
[jck287213@shell.ceshiren.com test]$ echo ‘1
2
3’ | awk ‘/1/’
1
[jck287213@shell.ceshiren.com test]$ echo ‘1
2
3’ | awk ‘/1/,NR==2’(整行匹配1,并且输出第2行)
1
2
[jck287213@shell.ceshiren.com test]$ echo ‘1
2
3’ | awk ‘/1/,NR==3’(整行匹配1,并且输出2行和3行)
1
2
3

action 行为表达式 {action}

  • 打印 {print $0} {print $2}
  • 赋值 {$1="abc"}
  • 处理函数
  • 原始内容 $0
  • 更新后内容 {$1=$1;print $0}

[jck287213@shell.ceshiren.com test]$ echo ‘a b c d’ | awk ‘{OFS=“|”;$1=$1;print $0}’
a|b|c|d
[jck287213@shell.ceshiren.com test]$ echo ‘a b c d’ | awk ‘{print $0;OFS=“|”;$1=$1;print $0}’
a b c d
a|b|c|d

单行转多行

echo 1:2:3 | awk ‘BEGIN{RS=“:”}{print $0}’
1
2
3
[jck287213@shell.ceshiren.com test]$ echo 1:2:3|awk ‘BEGIN{RS=“:”}{print $0}’
1
2
3

多行变单行

echo '1
2
3' | awk 'BEGIN{RS="";FS="\n";OFS=":"}{$1=$1;print $0}'
1:2:3

[jck287213@shell.ceshiren.com test]$ echo ‘1
2
3’|awk ‘BEGIN{RS=“”;FS=“\n”;OFS=“:”}{$1=$1;print$0}’
1:2:3

echo '1
2
3' | awk 'BEGIN{ORS=":"}{$1=$1;print $0}'
1:2:3:

计算平均数

echo ‘1,10
2,20
3,30’ | awk ‘BEGIN{total=0;FS=“,”}{total+=$2}END{print total/NR}’
20

awk 的词典结构 array

  • array 是稀疏矩阵,类似 python 的词典类型
  • 统计多家机构的营业额
  • 统计多家机构的营业额平均值

echo ‘a, 1, 10
a, 2, 20
a, 3, 30
b, 1, 5
b, 2, 6
b, 3, 7’ | awk ‘{data[$1]+=$3}
END{for(k in data) print k,data[k]}’
a, 60
b, 18

echo ‘a, 1, 10
a, 2, 20
a, 3, 30
b, 1, 5
b, 2, 6
b, 3, 7’ | awk ‘{data[$1]+=$3;count[$1]+=1;}
END{for(k in data) print k,data[k]/count[k]}’
a, 20
b, 6

[jck287213@shell.ceshiren.com test]$ head -5 uniq_demo.txt | awk ‘{OFS=" % ";$1=$1;print $0}’(指定分隔符输出)
ck141906 % pts/0 % 120.52.147.49
ck140081 % pts/13 % 113.65.231.23
ck140081 % pts/12 % 113.65.231.23
ck140081 % pts/4 % 221.219.101.182
82894931 % pts/12 % 36.112.85.179

[jck287213@shell.ceshiren.com test]$ top -b -n 1 | grep Cpu( 1. # -b -n 1 表示只需要1次输出结果)
%Cpu(s): 3.0 us, 3.0 sy, 0.0 ni, 93.9 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st
[jck287213@shell.ceshiren.com test]$ top -b -n 1 | grep Cpu | awk -F “,” ‘{print $4}’( 1. #输出cpu空闲率的字段
85.7 id
[jck287213@shell.ceshiren.com test]$ head -5 uniq_demo.txt | awk -F " " ‘{print $3}’(获取第三段内容)
120.52.147.49
113.65.231.23
113.65.231.23
221.219.101.182
36.112.85.179
[jck287213@shell.ceshiren.com tetop -b -n 1 | grep Cpu | awk -F “,” ‘{print $4}’$3}’
90.9 id
[jck287213@shell.ceshiren.com test]$ top -b -n 1 | grep Cpu | awk -F “,” ‘{print $4}’| awk ‘{print $1}’(#输出Cpu空闲率))
87.9

显示时间
[jck287213@shell.ceshiren.com test]$ date +“%Y%m%d”
20231012
[jck287213@shell.ceshiren.com test]$ date +“%Y%m01”
20231001
[jck287213@shell.ceshiren.com test]$ date +“%F %H:%M:%S”
2023-10-12 22:47:32

过滤文本中重复行数

[jck287213@shell.ceshiren.com test]$ head -n 5 uniq_demo.txt |awk ‘{print $3}’| awk ‘{a[$1]++}END{fiin a){print i,a[i]}}’
36.112.85.179 1
113.65.231.23 2
221.219.101.182 1
120.52.147.49 1

[jck287213@shell.ceshiren.com test]$ head -n 5 /etc/passwd | awk ‘//bin/bash$/{print $0}’
root:x:0:0:root:/root:/bin/bash
[jck287213@shell.ceshiren.com test]$ cat /etc/p | awk ‘/^root/{print $0}’(#输出以 root 开头的行)
root:x:0:0:root:/root:/bin/bash
[jck287213@shell.ceshiren.com test]$ cat /etc/passwd | awk -F “:” ‘/^root/{print $1,$3,$NF}’(#加上bin要使用反斜杠输出以bash结尾的行
root 0 /bin/bash

[jck287213@shell.ceshiren.com test]$ grep -c “/bin/bash$” /etc/passwd(统计以/bin/bash 结尾的行数)
8496
[jck287213@shell.ceshiren.com test]$ awk ‘/bin/bash/ {print | “wc -l”}’ /etc/passwd(统计以/bin/bash 结尾的行数)
8496