续正则表达式与Linux文本三剑客Day3

sed练习

准备文件

sed1.txt

1
2
3
4
5
6
7
8
9
10
11
12
13
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
sync:x:5:0:sync:/sbin:/bin/sync
shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
halt:x:7:0:halt:/sbin:/sbin/halt
mail:x:8:12:mail:/var/spool/mail:/sbin/nologin
operator:x:11:0:operator:/root:/sbin/nologin
games:x:12:100:games:/usr/games:/sbin/nologin
ftp:x:14:50:FTP User:/var/ftp:/sbin/nologin
nobody:x:99:99:Nobody:/:/sbin/nologin
systemd-network:x:192:192:systemd Network Management:/:/sbin/nologin
dbus:x:81:81:System message bus:/:/sbin/nologin

sed2.txt

1
2
3
4
5
6
7
8
 I like my lover.
I love my lover.
He likes his lovers.
He loves his lovers.
#she loves her cat.
i want ride my bike.


题目

替换文件中root为commen,只替换一次,与替换所有

只替换一次(每一行第一次出现的root)

1
2
3
4
5
6
7
8
9
[root@localhost ~]# grep "root" sed1.txt
root:x:0:0:root:/root:/bin/bash
operator:x:11:0:operator:/root:/sbin/nologin
######
[root@localhost ~]# sed -n 's/root/commen/p' sed1.txt
commen:x:0:0:root:/root:/bin/bash
operator:x:11:0:operator:/commen:/sbin/nologin
######写入文件,不演示结果了,和上面一样的
[root@localhost ~]# sed -i 's/root/commen/' sed1.txt

替换所有

1
2
3
4
5
6
7
8
9
[root@localhost ~]# grep "root" sed1.txt
root:x:0:0:root:/root:/bin/bash
operator:x:11:0:operator:/root:/sbin/nologin
#######
[root@localhost ~]# sed -n 's/root/commen/gp' sed1.txt
commen:x:0:0:commen:/commen:/bin/bash
operator:x:11:0:operator:/commen:/sbin/nologin
########
[root@localhost ~]# sed -i 's/root/commen/g' sed1.txt

替换文件所有的commen为root,且仅仅打印替换的结果

上一题中间过程已经演示了

1
2
3
4
5
6
7
[root@localhost ~]# sed -n 's/root/commen/p' sed1.txt
commen:x:0:0:root:/root:/bin/bash
operator:x:11:0:operator:/commen:/sbin/nologin
#######
[root@localhost ~]# sed -n 's/root/commen/gp' sed1.txt
commen:x:0:0:commen:/commen:/bin/bash
operator:x:11:0:operator:/commen:/sbin/nologin

替换前10行b开头的用户,改为c,且仅显示替换的结果

1
2
3
4
[root@localhost ~]# grep "^b" sed1.txt
bin:x:1:1:bin:/bin:/sbin/nologin
[root@localhost ~]# sed -n '1,10s/^bin/c/p' sed1.txt
c:x:1:1:bin:/bin:/sbin/nologin

替换前10行b开头的用户,改为c,且将m开头的行,改为M,且仅仅显示替换的结果

1
2
3
[root@localhost ~]#  sed -n -e '1,10s/^bin/c/p' -e '1,10s/^m/M/p'  sed1.txt
c:x:1:1:bin:/bin:/sbin/nologin
Mail:x:8:12:mail:/var/spool/mail:/sbin/nologin

删除四行后面的所有行

使用d内置命令符时,删除行时,不需要加-n参数

1
2
3
4
5
[root@localhost ~]# sed '5,$d' sed1.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
sync:x:5:0:sync:/sbin:/bin/sync

删除从root开始到ftp之间的行

知道行号可以直接用n,m匹配,下面为不知道时的写法

1
2
3
4
[root@localhost ~]# sed '/^root/,/^ftp/d' sed1.txt
nobody:x:99:99:Nobody:/:/sbin/nologin
systemd-network:x:192:192:systemd Network Management:/:/sbin/nologin
dbus:x:81:81:System message bus:/:/sbin/nologin

将文件中空白字符开头的行,添加注释符

1
2
3
4
5
6
7
8
9
[root@localhost ~]# sed -e 's/^[[:space:]]/#/g' -e 's/^$/#/g' sed2.txt
#I like my lover.
I love my lover.
He likes his lovers.
#He loves his lovers.
#she loves her cat.
i want ride my bike.
#
#

删除文件的空白和注释行

执行多个匹配

  • 参数-e

  • 分号;

1
2
3
4
5
6
7
8
9
10
###使用参数-e
[root@localhost ~]# sed -e '/^[[:space:]]/d' -e '/^$/d' -e '/^#/d' sed2.txt
I love my lover.
He likes his lovers.
i want ride my bike.
###使用分号;
[root@localhost ~]# sed -e '/^[[:space:]]/d;/^$/d;/^#/d' sed2.txt
I love my lover.
He likes his lovers.
i want ride my bike.

给文件前三行,添加@符号

思路:匹配第一个字符,把第一个字符替换成@符号后,引用匹配到的第一个字符

1
2
3
4
5
6
7
8
9
[root@localhost ~]# sed -r '1,3s/(^.)/@\1/' sed2.txt
@ I like my lover.
@I love my lover.
@He likes his lovers.
He loves his lovers.
#she loves her cat.
i want ride my bike.


取出IP地址

思路:取出IP地址所在行,删除前后不需要的内容

ifconfig命令找不到如何解决?

每个人的配置不一样,请先使用ifconfig看一下自己用的是哪张网卡,然后ifconfig <网卡名>就可以只打印该网卡的信息。

我还可以用ip a的方式查到IP信息。

1
2
3
4
5
6
[root@localhost ~]# ifconfig ens33|sed '2p' -n|sed 's/^.*inet[[:space:]]//;s/netmask.*//'
192.168.41.100
####减少使用管道符
[root@localhost ~]# ifconfig ens33|sed '2s/^.*inet[[:space:]]//;s/netmask.*//p' -n
192.168.41.100
####还可以用参数-e这里就不再写了,大家可以自己试试

找出系统版本

只想要版本号如:12

(原本是7.9.2009,这里我是修改文件)

1
2
[root@localhost ~]# cat /etc/centos-release
CentOS Linux release 12.9.2009 (Core)
1
2
3
[root@localhost ~]# sed -r 's/^.*release[[:space:]]*([^.]+).*/\1/p' /etc/centos-release -n
12
###如果不使用([^.])+那么结果会只匹配到1

awk练习

准备文件

awk1.txt

awk3.txt

1
2
3
4
5
6
7
8
9
10
11
12
Xiao Yang:[86] 675-161-111:10:20

John Mai:[1] 123-321-111:16:55

Tom Catty:[2] 444-555-444:45:12

Maiky Savage:[5] 221-125-011:11:87

Mati Mada:[7] 484-540-001:454:44

Chet Main:[86] 655-144-111:20:10

/etc/passwd

介绍一下passwd文件的结构

各字段含义

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
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
shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
halt:x:7:0:halt:/sbin:/sbin/halt
mail:x:8:12:mail:/var/spool/mail:/sbin/nologin
operator:x:11:0:operator:/root:/sbin/nologin
games:x:12:100:games:/usr/games:/sbin/nologin
ftp:x:14:50:FTP User:/var/ftp:/sbin/nologin
nobody:x:99:99:Nobody:/:/sbin/nologin
systemd-network:x:192:192:systemd Network Management:/:/sbin/nologin
dbus:x:81:81:System message bus:/:/sbin/nologin
polkitd:x:999:998:User for polkitd:/:/sbin/nologin
sshd:x:74:74:Privilege-separated SSH:/var/empty/sshd:/sbin/nologin
postfix:x:89:89::/var/spool/postfix:/sbin/nologin
chrony:x:998:996::/var/lib/chrony:/sbin/nologin
commen:x:1000:1000::/home/commen:/bin/bash

题目

在当前系统中打印所有普通用户的用户名和主目录

1
2
3
4
5
6
[root@localhost ~]# awk -F ":" '{print $1,$(NF-1)}' /etc/passwd
root /root
bin /bin
...
...
#省略了哈

打印UID大于500的用户和其UID以及默认shell解释器

1
2
3
4
[root@localhost ~]# cat -n /etc/passwd|awk -F ":" '$3>500{print $1,$NF}'
16 polkitd /sbin/nologin
19 chrony /sbin/nologin
20 commen /bin/bash

给awk1.txt前两行添加#号

1
2
3
4
5
6
7
[root@localhost ~]# awk 'NR<3{print "#"$0}' awk1.txt
#a1 a2 a3 a4
#b1 b2 b3 b4
######
[root@localhost ~]# awk 'NR<=2{print "#"$0}' awk1.txt
#a1 a2 a3 a4
#b1 b2 b3 b4

统计所有电话号码不带区号,不显示空行

1
2
3
4
5
6
7
[root@localhost ~]# awk -F "[ :]" '!/^$/{print $4}' awk3.txt
675-161-111
123-321-111
444-555-444
221-125-011
484-540-001
655-144-111

[ :]表示以空格或冒号分隔

!/^$/表示不匹配空行,!的作用是取反

显示Tom的电话

1
2
[root@localhost ~]#  awk -F "[ :]" '/^Tom/{print $1,$4}' awk3.txt
Tom 444-555-444

显示所有M开头的姓和手机号带区号

1
2
3
4
[root@localhost ~]# awk -F "[: ]" '$2~/^M/{print $2,$3$4}' awk3.txt
Mai [1]123-321-111
Mada [7]484-540-001
Main [86]655-144-111

$2~表示针对第二列使用模式匹配

显示所有区号为86的人名

1
2
3
[root@localhost ~]# awk -F "[: ]" '$3~/\[86\]/{print $1}' awk3.txt
Xiao
Chet

\[86\]使用了反斜杠转义

显示Main除了电话号码的其它信息,并在信息前加$符

1
2
[root@localhost ~]# awk -F "[: ]" '/Main/{print "$"$(NF-1),"$"$NF}' awk3.txt
$20 $10

显示所有人的“姓+,+名”

1
2
3
4
5
6
7
[root@localhost ~]# awk -F "[: ]" -v OFS="," '!/^$/{print $2,$1}' awk3.txt
Yang,Xiao
Mai,John
Catty,Tom
Savage,Maiky
Mada,Mati
Main,Chet

-v OFS=","效果等同于$2","$1

删除空白行

1
2
3
4
5
6
7
[root@localhost ~]# awk '!/^$/' awk3.txt
Xiao Yang:[86] 675-161-111:10:20
John Mai:[1] 123-321-111:16:55
Tom Catty:[2] 444-555-444:45:12
Maiky Savage:[5] 221-125-011:11:87
Mati Mada:[7] 484-540-001:454:44
Chet Main:[86] 655-144-111:20:10