linux三剑客

所谓三剑客就是linux中三个可以用linux正则表达式的命令

  • grep 过滤
  • sed 取行 替换
  • awk 取列

环境准备

# passwd.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
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

grep

格式:grep 选项 正则 文件

作用:在文件中找到符合正则条件的行

选项

  • -v 取反
  • -i 不区分大小写
  • -n 显示匹配到的行在源文件中的行号
  • -o 只输出匹配到的内容
  • -E 扩展正则
  • -w 按单词匹配
  • -A -B -C 可以显示匹配行的前后几行 -A3 后三行 -B3 前三行 -C3前后三行
  • -P 可以使用Perl正则语法

例子

# 以noLogin结尾的 不区分大小写 可以去掉-i试试
[root@centos76 data]# grep -i "noLogin$" passwd.txt 
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
mail:x:8:12:mail:/var/spool/mail:/sbin/nologin
# 加上-v试试  变成不以nologin结尾的了
[root@centos76 data]# grep -iv "noLogin$" passwd.txt 
root:x:0:0:root:/root:/bin/bash

sync:x:5:0:sync:/sbin:/bin/sync
shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown

halt:x:7:0:halt:/sbin:/sbin/halt

# 再加上-n试试  显示了在源文件中的行号
[root@centos76 data]# grep -ivn "noLogin$" passwd.txt 
1:root:x:0:0:root:/root:/bin/bash
2:
7:sync:x:5:0:sync:/sbin:/bin/sync
8:shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
9:
10:halt:x:7:0:halt:/sbin:/sbin/halt

grep -E 相当于egrep 可以使用linux正则表达式中的扩展正则

# -o 只显示匹配到的内容 而不是显示整行
[root@centos76 data]# grep -ino "noLogin$" passwd.txt 
3:nologin
4:nologin
5:nologin
6:nologin
11:nologin
# -w 按单词匹配 所以用nologin可以匹配到 用no不行
[root@centos76 data]# grep -w "nologin" passwd.txt 
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
mail:x:8:12:mail:/var/spool/mail:/sbin/nologin
[root@centos76 data]# grep -w "no" passwd.txt 
[root@centos76 data]#

sed

作用

流编辑器 可以对文本进行增删改查

格式

sed [OPTION]... '取什么 取到后做什么' [input-file]...

选项

  • -n 取消默认输出
  • -r 扩展正则
  • -i 直接修改文件
  • -e 多次编辑

sed -n '1,3p' passwd.txt 取1到3行并打印

# 准备实验对象passwd.txt
[root@centos76 data]# cat /etc/passwd > passwd.txt
[root@centos76 data]# sed -n '1,3p' passwd.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

-n选项取消默认打印,去掉后会发现1到3行打印了两遍,其他行也都打印了,自己试试体会下。
'1,3p' 这个就是格式中的脚本部分,作用是:取什么 取到后做什么
1,3表示取1到3行 p表示取到后打印
改成'4p'自己试下。

sed -n '/root/p' passwd.txt 取到包含root的行并打印

[root@centos76 data]# sed  -n '/root/p' passwd.txt 
root:x:0:0:root:/root:/bin/bash
operator:x:11:0:operator:/root:/sbin/nologin

//之间的内容 世界是正则表达式

sed "1,10d" passwd.txt 删除1到10行并打印剩下的行

[root@centos76 data]# sed  "1,10d" passwd.txt 
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
nginx:x:997:995:nginx user:/var/cache/nginx:/sbin/nologin
ocean:x:1000:1000::/home/ocean:/bin/bash

执行上面这些删除命令后,你会发现passwd.txt源文件并没有发生变化,如果想修改源文件,需要加-i参数,-i.bak会先备份后修改源文件,建议修改前备份

sed -i.bak "1,10d" passwd.txt 备份后在源文件中删除1到10行,真实删除

[root@centos76 data]# sed -i.bak  "1,10d" passwd.txt
[root@centos76 data]# wc passwd.txt
 11  20 560 passwd.txt
[root@centos76 data]# wc passwd.txt.bak 
 21  30 945 passwd.txt.bak

建议:操作前备份,操作后检查

sed "s/nologin/NOLOGIN/g" passwd.txt 把nologin替换成NOLOGIN

s/查找的内容/替换的内容/g s表示替换 g表示全局,///可以替换成###,@@@,只要可以分割即可//之间实际上是正则表达式

[root@centos76 data]# sed "s/nologin/NOLOGIN/g" passwd.txt
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
nginx:x:997:995:nginx user:/var/cache/nginx:/sbin/NOLOGIN
ocean:x:1000:1000::/home/ocean:/bin/bash

sed '2a hello' passwd.txt 第二行之后添加一行hello是第三行
sed '2i hello' passwd.txt 第二行之前插入一行hello是第二行

sed 获取ip地址

sed默认不支持扩展正则 加上-r支持扩展正则
s#A#B#g 用来把A替换成B

# ipv4
> A=`^.*inet (([0-9]{1,3}\.){3}[0-9]{1,3}).*$`
> B=`\1` 分组引用,引用`([0-9]{1,3}\.){3}[0-9]{1,3}`
[root@centos76 ~]# ip address show ens33|grep "inet "|sed -r 's#^.*inet (([0-9]{1,3}\.){3}[0-9]{1,3}).*$#\1#g'
192.168.100.100
# ipv6
> A=`^.*inet6 (([0-9a-fA-F]{,4}:){5}[0-9a-fA-F]{,4}).*$`
> B=`\1` 分组引用,引用`([0-9a-fA-F]{,4}:){5}[0-9a-fA-F]{,4}`
[root@centos76 ~]# ip address show ens33|grep "inet6"|sed -r 's#^.*inet6 (([0-9a-fA-F]{,4}:){5}[0-9a-fA-F]{,4}).*$#\1#g'
fe80::6ac3:3104:7003:e3fe

小结

  • sed -n {1,4p} 文件名 按行查找-取什么:1-4行,取到后做什么:p打印。
  • sed -n '/A/p' 文件名 按正则查找-取什么 :能匹配正则A的行,取到后做什么:p打印。
  • sed "s/A/B/g" 文件名 替换-把正则A匹配的内容替换成B,A中可以分组,B中可以引用。

awk

作用

用-F指定的分割符将文件分割,分割后
1代表第一列
NF代表最后一列
$(NF-1)代表倒数第二列
NF 列数
NR 行号
然后执行program指定的程序

格式

awk [options] -f progfile [--] file ...
awk [options] [--] 'program' file ... 下面讲的都是这个格式
'program'的格式是 '条件{动作}'

选项

  • -F 指定分割符

awk '/games/' passwd.txt

只有条件没有动作 表示过滤符合条件的行
条件可以是正则 /正则/ awk默认支持扩展正则
也可以是范围NR==1,NR==3 ,分割表示1到3行
也可以是多个条件 NR>=1 && NR<=3

[root@centos76 data]# awk '/games/' passwd.txt 
games:x:12:100:games:/usr/games:/sbin/nologin
[root@centos76 data]# awk 'NR==1,NR==3' passwd.txt 
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

awk -F':' '{print $1}' passwd.txt

只有动作没有条件 表示所有的行都要执行该program
这里指定了分割符为:,用分隔符把passwd.txt中的每一行分割成多个列
之后执行'{print $1}'这段程序
就是打印第一列的内容

[root@centos76 data]# awk -F':' '{print $1}' passwd.txt
games
ftp
nobody
systemd-network
dbus
polkitd
sshd
postfix
chrony
nginx
ocean
# 这里中间可以加上-- 
# --的作用是 明确--前面的部分是awk [options]
# 明确--后面的部分是'program' file ...
[root@centos76 data]# awk -F ':' -- '{print $1}' passwd.txt
games
ftp
nobody
systemd-network
dbus
polkitd
sshd
postfix
chrony
nginx
ocean

awk -F ':' 'NR==1,NR==3{print $1}' passwd.txt

既有条件又有动作 表示只对符合条件的行执行对应的动作

[root@centos76 data]# awk -F ':' 'NR==1,NR==3{print $1}' passwd.txt 
games
ftp
nobody

例子

sed专业取行

用sed将/etc/passwd文件中第一行到最后一行重定向到passwd.txt

# -n 和 p 配对 -n默认不打印 p打印  结果就是只打印符合条件的
sed -n '1,$p' /etc/passwd > passwd.txt

显示/etc/passwd的第三行到第七行

sed -n '3,7p' /etc/passwd
# 表示单个条件
awk 'NR>=3 && NR<=7' /etc/passwd
# , 表示范围 从第三行到第7行
awk 'NR==3,NR==7' /etc/passwd

awk专业取列

用sed取出passwd.txt中用户名为dbus的行中备注列

dbus:x:81:81:System message bus:/:/sbin/nologin #取出System message bus
ftp:x:14:50:FTP User:/var/ftp:/sbin/nologin     #取出FTP User

# -r 用来使用增强正则  n和p配对 g
# s#找什么#替换成什么#g 
sed -rn 's#([^:]*):([^:]*):([^:]*):([^:]*):([^:]*):([^:]*):([^:]*)#\5#gp' passwd.txt
[root@centos76 sjk]# sed -rn 's#dbus:([^:]*):([^:]*):([^:]*):([^:]*):([^:]*):([^:]*)#\4#p' passwd.txt
System message bus
[root@centos76 sjk]# sed -rn 's#ftp:([^:]*):([^:]*):([^:]*):([^:]*):([^:]*):([^:]*)#\4#p' passwd.txt
FTP User
[root@centos76 sjk]# awk -F: '$1=="dbus"{print $5}' passwd.txt 
System message bus
[root@centos76 sjk]# awk -F: '$1=="ftp"{print $5}' passwd.txt 
FTP User

使用awk取passwd.txt用户名及家目录并显示行号

[root@centos76 sjk]# awk -F: '{print NR,$1,$6}' passwd.txt |column -t
1   root             /root
2   bin              /bin
3   daemon           /sbin
4   adm              /var/adm

passwd.txt中uid>10时 显示整行

[root@centos76 sjk]# awk -F: '$3>10{print NR,$0}' passwd.txt
10 operator:x:11:0:operator:/root:/sbin/nologin
11 games:x:12:100:games:/usr/games:/sbin/nologin
12 ftp:x:14:50:FTP User:/var/ftp:/sbin/nologin
13 nobody:x:99:99:Nobody:/:/sbin/nologin
[root@centos76 data]# awk -F: '$1~/games/{print NR,$0}' passwd.txt
1 games:x:12:100:games:/usr/games:/sbin/nologin

你可能感兴趣的:(linux三剑客)