28_Linux基础-shell编程-awk

:点击此处或下方 以展开或折叠目录

/bin下面放二进制文件
lib 放系统的公共模块、公共库、公共工具
/dev设备文件

#标准输入、标准输出

/usr 安装的命令安装的模块 编译安装、rpm安装的程序

/boot 系统启动会到这里来找

/proc 保留正在运行的程序

/proc/sys 正在运行的内核参数进行修改
/etc/sysctl.conf 永久修改
[root@localhost net]# sysctl -p 生效

/run 保存pid文件

/var/log 系统日志


一. 脚本调试 -x

1
2
3
4
5
6
7
8
#示例:脚本的调试  -x
[root@cPen_A lianxi]# bash -x test.sh
+ ls
aaa2 aaa.py d.md5 mod1.py __pycache__ test_class2.py test_class.py test.sh
+ echo ok
ok
+ echo err
err

二. 小数计算

1
2
3
4
5
6
7
#示例:小数计算
[root@cPen_A lianxi]# echo "scale=2;5/3" |bc
1.66
[root@cPen_A lianxi]# echo "5 3" |awk '{print $1/$2}'
1.66667
[root@cPen_A lianxi]# echo "5 3" |awk '{printf "%.2f",$1/$2}'
1.67

三. 打印奇数

1
2
3
4
#示例:打印奇数
[root@cPen_A lianxi]# for i in `seq 1 2 100` ;do echo $i;done

#注:或者类似C语言for循环写法

四. 合并文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
#示例:合并文件
把用户名字和用户金额统一在一起
#注:把2个文件按照列合并

[root@cPen_A shell_test]# cat user.txt
100 cp1
200 cp2
300 cp3
[root@cPen_A shell_test]# cat money.txt
100 $500
300 $600
200 $400
-----------------------------------------------------
[root@cPen_A shell_test]# cat money.txt |sort -t " " -n >money2.txt
[root@cPen_A shell_test]# cat user.txt |sort -t " " -n >user2.txt
[root@cPen_A shell_test]# cat user2.txt
100 cp1
200 cp2
300 cp3
[root@cPen_A shell_test]# cat money2.txt
100 $500
200 $400
300 $600
[root@cPen_A shell_test]# join user2.txt money2.txt
100 cp1 $500
200 cp2 $400
300 cp3 $600

[root@cPen_A shell_test]# paste user2.txt money2.txt
100 cp1 100 $500
200 cp2 200 $400
300 cp3 300 $600

-----------------------------------------------------
while read user_id user_name
do
while read user_id2 user_money
do
if [[ $user_id == $user_id2 ]]
then
echo $user_id $user_name $user_money >> user_money.txt
fi
done < money.txt
done < user.txt


sed处理文本

vim替换文本,用替换模式 按r

sed在文本外部操作文本里面的内容。做更新替换和删除(比如修改一键化安装脚本 配置文件 用sed去修改)

http://c.biancheng.net/linux/sed.html

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
[root@cPen_A shell_test]# vim test.txt
aa
bb
cc
abc
def
[root@cPen_A shell_test]# sed '/a/d' test.txt
bb
cc
def
[root@cPen_A shell_test]# cat test.txt
aa
bb
cc
abc
def
[root@cPen_A shell_test]# sed -i '/a/d' test.txt #注:真正删除成功
[root@cPen_A shell_test]# cat test.txt
bb
cc
def

五. 文本处理

1.文本处理(请使用shell脚本让其满足下列特性):

(1)给下列含有大写字母的行,在大写字母后追加数字2020 --》sed

abcdSdddde

islHishbxld

goBkefji

daanshXxge

1
2
3
4
5
6
sed -i‘s/oldword/newword/g’ c.txt
#注:s substitute替换
&代表前面匹配的oldword

[root@cPen_A ~]# cat c.txt |sed 's/[A-Z]/&2020/g'
[root@cPen_A ~]# sed -i 's/[A-Z]/&2020/g' c.txt #注:对源文件做修改
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
(2)请取出下列以逗号分割符最后一个字段不为0的行,并对最后一个字段以100为最小单位取整取正
   000001,2,115
   000002,2,1,0
   000002,2,1,-200
awk,tr

[root@cPen_A ~]# vim c.txt
? ?000001,2,115
? ?000002,2,1,0
? ?000002,2,1,-200
[root@cPen_A ~]# cat c.txt |tail -3|awk -F, '$NF != 0{print $1,int($NF/100)}'
? ?000001 1
? ?000002 -2
[root@cPen_A ~]# cat c.txt |tail -3|awk -F, '$NF != 0{print $0,int($NF/100)}'|tr -d "-"
? ?000001,2,115 1
? ?000002,2,1,200 2
[root@cPen_A ~]# cat c.txt |tail -3|awk -F, '$NF != 0{print $0,sqrt(int($NF/100)*int($NF/100))}'
? ?000001,2,115 1
? ?000002,2,1,-200 2
[root@cPen_A ~]# cat c.txt |tail -3|awk -F, '$NF != 0{print $0,sqrt(int($NF/100)*int($NF/100)),length($1)}'
? ?000001,2,115 1 9
? ?000002,2,1,-200 2 9
#注:$NF != 0 最后一项不为0
#注:$0 指全部。sqrt开平方

AWK 里有很多的内置函数
int()
sqrt() 开根号
length()

[root@cPen_A ~]# a=-488
[root@cPen_A ~]# echo ${a#-} #注:删除-号
488

六. awk

awk 是什么?

​ awk是linux里的一个文本处理的命令(工具) --> 程序 --> c语言

unix --> awk

​ 为什么要使用awk?

​ 截取内容

bc进行小数运算

awk也可以

字段:field --> 列 column

name age sex grade

cali 18 M 70

rose 19 F 90

#注:CSV文件 以,作为分割的文件

$0 存储的是整行数据

每个数据存入$1-$7中

AWK 默认的分隔符是空白(空格、tab)

输入分隔符

​ -F

输出分隔符

​ ,

1
2
3
4
[root@cPen_A lianxi]# cat /etc/passwd|awk -F":" '{print $1$3$7}'
root0/bin/bash
[root@cPen_A lianxi]# cat /etc/passwd|awk -F":" '{print $1,$3,$7}'
root 0 /bin/bash

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
[root@cPen_A lianxi]# cat /etc/passwd|awk -F: 'BEGIN{print "######start######"} /bash$/{print $1,$7}END{print "######end######"}'
######start######
root /bin/bash
sanchuang /bin/bash
……
chen223344 /bin/bash
######end######
#注:/bash$ 以bash结尾的行

#示例:统计有多少行
[root@cPen_A lianxi]# cat /etc/passwd|awk -F: 'BEGIN{i=0} {i++} END{print i}'
65
#注:不需要用$,因为引用的不是变量
#注:多条命令使用,在{花括号}里放;号
#注:~波浪符号 模糊匹配 ~/feng/; || 或;&& 且

AWK内置变量

AWK内置变量

NR 代表行号 number of record --> record 记录 --> 行

NF 代表一行的字段数量 number of field

NF表示最后一个字段;NF 表示最后一个字段;(NF-1)倒数第一个字段

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
[root@cPen_A lianxi]# cat /etc/passwd |awk -F: 'BEGIN{num=0;print "开始统计/etc/passwd文件"} $1 ~ /feng/ || $3 > 1005 {print NR,NF,$1,length($1),$(NF-1),$NF,$3;num++}END{print "统计结束",num}'
开始统计/etc/passwd文件
24 7 chenpeng1 9 /home/chenpeng1 /bin/bash 1100
25 7 chenpeng2 9 /home/chenpeng2 /bin/bash 1200
……
65 7 nfsnobody 9 /var/lib/nfs /sbin/nologin 65534
统计结束 37

-------------------------------------------------------------------
#示例:AWK过滤功能
[root@cPen_A lianxi]# cat /etc/passwd|awk -F: '/xiexy/'
[root@cPen_A lianxi]# cat /etc/passwd|egrep "xiexy"
#示例:AWK截取功能
[root@cPen_A lianxi]# who |awk '{print $2}'
tty1
pts/2
[root@cPen_A lianxi]# who |awk '{print $2,$4}'
tty1 11:23
pts/2 09:38
#示例:自定义的字符串和字段拼接
[root@cPen_A lianxi]# who |awk '{print "time:"$4,"name:"$2}'
time:11:23 name:tty1
time:09:38 name:pts/2

-------------------------------------------------------------------
#示例:/^[^abcdefg]/ 不是以abcdefg开头的行
[root@cPen_A lianxi]# cat /etc/passwd|awk -F: '/^[^abcdefg]/{print $1,$7}'
#示例:/^[^A-z]/ 不是A-z字母开头的行
[root@cPen_A lianxi]# cat /etc/passwd|awk -F: '/^[^A-z]/{print $1,$7}'
#示例:指定2个分割符
[root@cPen_A lianxi]# cat /etc/passwd|tail -1|awk -F[:/] '{print $8}'
lib

awk命令的操作符

awk命令的操作符
比较操作符:匹配符号 ~ !~

1
2
3
4
5
6
7
8
#示例:
[root@cPen_A lianxi]# who
root tty1 2020-12-23 11:23
root pts/2 2021-01-08 09:38 (192.168.0.119)
[root@cPen_A lianxi]# who|awk '$2 ~ /pts/{print $0}'
root pts/2 2021-01-08 09:38 (192.168.0.119)

[root@cPen_A lianxi]# cat /etc/passwd|awk -F: '$1 ~/deng/ && $3>1058 && $NF ~/bash$/'

文本数据表达式

文本数据表达式:
== 精确匹配
~ 模糊匹配

1
2
3
4
5
6
7
8
9
10
11
12
[root@cPen_A lianxi]# awk -F: '$3 ~ /\<...\>/ {print $1,$3}' /etc/passwd
systemd-network 192
polkitd 999
chrony 998
nginx 997
[root@cPen_A lianxi]# awk -F: '$3 ~ /\<.{3}\>/ {print $1,$3}' /etc/passwd
systemd-network 192
polkitd 999
chrony 998
nginx 997

[root@cPen_A lianxi]# cat /etc/passwd|awk -F: '$1 ~ /deng/ {print $1}'

awk 内置变量和函数

awk 内置变量和函数?
NF 每行$0的字段数
NR 当前处理的行号
FS 当前的输入分隔符,默认是空白字符(空格和tab) field separator
OFS 当前的输出分隔符,默认是空格字符(空格) output field separator

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
示例:
[root@cPen_A lianxi]# cat /etc/passwd|awk -F: '{print NR,$0}'
1 root:x:0:0:root:/root:/bin/bash #注:NR行号
2 bin:x:1:1:bin:/bin:/sbin/nologin
[root@cPen_A lianxi]# cat /etc/passwd|awk -F: '{print NR,$0,NF}'
1 root:x:0:0:root:/root:/bin/bash 7
2 bin:x:1:1:bin:/bin:/sbin/nologin 7
[root@cPen_A lianxi]# cat /etc/passwd|awk -F: '{print NR,$0,$NF}'
1 root:x:0:0:root:/root:/bin/bash /bin/bash
2 bin:x:1:1:bin:/bin:/sbin/nologin /sbin/nologin

[root@cPen_A lianxi]# cat /etc/passwd|awk 'FS=":";OFS="#"{print NR,$0,$NF}'
root:x:0:0:root:/root:/bin/bash
1#root:x:0:0:root:/root:/bin/bash#root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
2#bin:x:1:1:bin:/bin:/sbin/nologin#/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
#推荐使用-F指定输入分隔符

===========================================================================================
使用NF变量显示passwd文件倒数第二列的内容
[root@cPen_A ~]# cat /etc/passwd|awk -F: '{print $(NF-1)}'

----------------------------------------------------------
显示passwd文件中第5到第10行的用户名
[root@cPen_A ~]# cat /etc/passwd|awk -F: 'NR >= 5 && NR <= 10 {print $1}'
[root@cPen_A ~]# cat /etc/passwd|awk -F: 'NR >= 5 && NR <= 10 {print NR,$1}'

----------------------------------------------------------
显示passwd文件中第7列不是bash的用户名
[root@cPen_A ~]# cat /etc/passwd|awk -F: '$7 ~ /bash/ {print NR,$1}'

----------------------------------------------------------
显示passwd文件中行号是5结尾的行号和行
[root@cPen_A ~]# cat /etc/passwd|awk -F: 'NR ~ /5$/ {print NR,$1}'

----------------------------------------------------------
用ip add只显示ip(不能使用tr或者cut命令)
[root@cPen_A ~]# ip add|awk '$NF ~ /ens33/ {print $0}'
inet 192.168.0.118/24 brd 192.168.0.255 scope global noprefixroute dynamic ens33
[root@cPen_A ~]# ip add|awk '$NF ~ /ens33/ {print $2}'
192.168.0.118/24
[root@cPen_A ~]# ip add|awk '$NF ~ /ens33/ {print $2}'|awk -F/ '{print $1}'
192.168.0.118

----------------------------------------------------------
[root@localhost lianxi]# yum install net-tools -y
先使用ifconfig,使用awk显示eth0的入站流量和出站流量(字节)
[root@cPen_A ~]# ifconfig|head -8|awk '$1 ~ /RX/ && $4 ~ /bytes/ || $1 ~ /TX/ && $4 ~ /bytes/ {print $0}'
RX packets 494598 bytes 38344433 (36.5 MiB)
TX packets 17025 bytes 1718505 (1.6 MiB)
[root@cPen_A ~]# ifconfig|head -8|awk '$1 ~ /RX/ && $4 ~ /bytes/ || $1 ~ /TX/ && $4 ~ /bytes/ {print $5}'
38372669
1719743
[root@cPen_A ~]# ifconfig|head -8|awk '$0 ~ /RX.*bytes|TX.*bytes/ {print $5}'
38476866
1744541

#注:当有&&或者||,&&(and)的优先级高

----------------------------------------------------------
使用awk命令统计以r开头的用户数目,显示如下效果
[root@cPen_A ~]# cat /etc/passwd|awk -F: 'BEGIN{i=0} $1 ~ /^r/ {print $1;i++} END{print i}'
root
rpc
rpcuser
3