9.1 正则介绍

正则表达式,又称规则表达式,计算机科学的一个概念,正则表达式是对字符串操作的一种逻辑公式,就是用事先定义好的一些特定字符、及这些特定字符的组合,组成一个“规则字符串”,这个“规则字符串”用来表达对字符串的一种过滤逻辑,在很多文本编辑器或其他工具里,正则表达式通常被用来检索和/或替换那些符合某个模式的文本内容。许多程序设计语言都支持利用正则表达式进行字符串操作。 元字符 . 点匹配任意一个字符 * 星号匹配0个或多个*号前面的字符,例如:a*表示0个或多个a,(0-n) .* 点星表示通配符,任意个任意字符,即所有都匹配 ? 问号匹配0个或1个?号前面的字符(0-1) (除了 awk,grep和sed需要脱意,“grep -E=egrep” 和“sed -r”可以直接使用,不用额外脱意) + 加号匹配1个或多个+号前面的字符 (1-n)一般需要脱意使用(除了 awk,grep和sed需要脱意,“grep -E=egrep” 和“sed -r”可以直接使用,不用额外脱意) \ 脱意符,把有特殊含义的字符还原成普通字符 ^ 匹配一行的开头,如:^what匹配以what开头的行 $ 匹配一行的结尾,如:what$匹配以what结尾的行 [ ] 匹配括号中的任何一个字符,如:[0-2]表示匹配0,1,2中的任意一个,[23]表示匹配2或者3,不是23 <, > 匹配单词(如:what)的开始(<)和结束(>)一般需要脱意使用(除了 awk,grep和sed需要脱意,“grep -E=egrep” 和“sed -r”可以直接使用,不用额外脱意)。

| 将两个匹配条件进行逻辑“或”(Or)运算。 一般需要脱意使用(除了 awk,grep和sed需要脱意,“grep -E=egrep” 和“sed -r”可以直接使用,不用额外脱意)。

? 匹配0或1个正好在它之前的那个字符。 一般需要脱意使用(除了 awk外,grep和sed需要脱意,“grep -E=egrep” 和“sed -r”可以直接使用,不用额外脱意)。

{n} {n1,n2}: 匹配前面字符出现的次数,如:a{2}表示a出现2次,a{2,5}表示a出现2到5次,一般需要脱意使用(除了 awk外,grep和sed需要脱意,“grep -E=egrep” 和“sed -r”可以直接使用,不用额外脱意)。

9.2grep / egrep工具

grep是一种强大的文本搜索工具,针对行进行操作,它能使用正则表达式搜索文本,并把匹配的行打印出来,egrep是grep的扩展 语法: grep [options] ‘关键字’ filename Options: -c:=count 行数,只显示匹配的总行数,不显示行的内容 -i:=ignore-case 不区分大小写 -n:=line-number 显示行号 -v:=revert-match 取反 -r,-R:=recursive(递归的,循环的)读取目录下的所有文件,包括子目录 -A:后面跟数字,过滤出符合要求的行以及下面n行 -B:同上,过滤出符合要求的行以及上面n行 -C:同上,同时过滤出符合要求的行以及上下各n行 -E:‘grep -E’ = egrep 1、不加任何选项,只过滤出关键字所在的行,并把行的内容打印出来

[root@localhost tmp]# grep 'root' test.txt 
root:x:0:0:root:/root:/bin/bash
operator:x:11:0:operator:/root:/sbin/nologin

在Linux中,grep默认带color选项

[root@localhost tmp]# which grep 
alias grep='grep --color=auto'
	/usr/bin/grep

2、-c只显示匹配的总行数,不显示行的内容

[root@localhost tmp]# grep -c 'root' test.txt                  #上面搜索出来有两行,所有这里显示2
2

3、-n打印符合的行,并把行号显示出来

[root@localhost tmp]# grep -n 'root' test.txt                #可以看到第1行和11行都有root
1:root:x:0:0:root:/root:/bin/bash
11:operator:x:11:0:operator:/root:/sbin/nologin

4、-i不区分关键字的大小写,会把整个文档都遍历一次,速度较慢

[root@localhost tmp]# echo "ROot/ROOT/" >>test.txt             #追加一行大小写混合的行到 test.txt
[root@localhost tmp]# grep -i 'root' test.txt                               #可以看到不管大写和小写都可以匹配
root:x:0:0:root:/root:/bin/bash
operator:x:11:0:operator:/root:/sbin/nologin
ROot/ROOT/

5、-v取向,把不包含关键字的行显示出来

[root@localhost tmp]# grep -v 'nologin' test.txt 
root:x:0:0:root:/root:/bin/bash
yy:iji#adklfjdl@fkjdkl?jfdkjk
sync:x:5:0:sync:/sbin:/bin/sync
shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
halt:x:7:0:halt:/sbin:/sbin/halt
luo:x:1001:1006::/home/luo:/bin/bash
ROot/ROOT/

6、-r/-R遍历目录下的(包括子目录下的)所有文件,把匹配的行显示出来

[root@adai003 localhost tmp]# tree                  #可以看到tmp目录下还有grep目录,grep目录下有个test1.txt文件
.
├── grep
│   └── test1.txt
└── test.txt
[root@localhost tmp]# grep -r 'root'                  #后面不加目录,表示过滤当前目录下的所有文件
test.txt:root:x:0:0:root:/root:/bin/bash
test.txt:operator:x:11:0:operator:/root:/sbin/nologin
grep/test1.txt:root:x:0:0:root:/root:/bin/bash
grep/test1.txt:operator:x:11:0:operator:/root:/sbin/nologin
[root@localhost tmp]# grep -R 'root'
test.txt:root:x:0:0:root:/root:/bin/bash
test.txt:operator:x:11:0:operator:/root:/sbin/nologin
grep/test1.txt:root:x:0:0:root:/root:/bin/bash
grep/test1.txt:operator:x:11:0:operator:/root:/sbin/nologin

7、-A后面跟数字n,表示过滤出符合要求的行以及下面n行

[root@localhost tmp]# grep -A2  'root' test.txt      #这里把匹配‘root'的行和后面两行都打印出来
root:x:0:0:root:/root:/bin/bash
yy:iji#adklfjdl@fkjdkl?jfdkjk
bin:x:1:1:bin:/bin:/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

8、-B后面跟数字n,表示过滤出符合要求的行以及下面n行

[root@localhost tmp]# grep -B2 'mail' test.txt 
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
--
luo:x:1001:1006::/home/luo:/bin/bash
saslauth:x:997:76:Saslauthd user:/run/saslauthd:/sbin/nologin
mailnull:x:47:47::/var/spool/mqueue:/sbin/nologin

9、-C后面跟数字n,表示过滤出符合要求的行以及上面n行和下面n行

[root@localhost tmp]# grep -C2 'luo' test.txt 
rpcuser:x:29:29:RPC Service User:/var/lib/nfs:/sbin/nologin
tcpdump:x:72:72::/:/sbin/nologin
luo:x:1001:1006::/home/luo:/bin/bash
saslauth:x:997:76:Saslauthd user:/run/saslauthd:/sbin/nologin
mailnull:x:47:47::/var/spool/mqueue:/sbin/nologin

grep正则表达式的一些应用 1、把包含数字的行显示过滤出来

[root@localhost tmp]# grep '[0-9]' 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
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:997:User for polkitd:/:/sbin/nologin
postfix:x:89:89::/var/spool/postfix:/sbin/nologin
sshd:x:74:74:Privilege-separated SSH:/var/empty/sshd:/sbin/nologin
chrony:x:998:996::/var/lib/chrony:/sbin/nologin
rpc:x:32:32:Rpcbind Daemon:/var/lib/rpcbind:/sbin/nologin
rpcuser:x:29:29:RPC Service User:/var/lib/nfs:/sbin/nologin
tcpdump:x:72:72::/:/sbin/nologin
luo:x:1001:1006::/home/luo:/bin/bash
saslauth:x:997:76:Saslauthd user:/run/saslauthd:/sbin/nologin
mailnull:x:47:47::/var/spool/mqueue:/sbin/nologin
smmsp:x:51:51::/var/spool/mqueue:/sbin/nologin
nginx:x:996:995:Nginx web server:/var/lib/nginx:/sbin/nologin
mysql:x:1002:1002::/home/mysql:/sbin/nologin

2、过滤出不包含数字的行

[root@localhost tmp]# grep -v '[0-9]' test.txt
yy:iji#adklfjdl@fkjdkl?jfdkjk
ROot/ROOT/

3、过滤出以#号开头的行

[root@localhost tmp]# grep  '^#' /etc/inittab 
# inittab is no longer used when using systemd.
#
# ADDING CONFIGURATION HERE WILL HAVE NO EFFECT ON YOUR SYSTEM.
#
# Ctrl-Alt-Delete is handled by /usr/lib/systemd/system/ctrl-alt-del.target
#
# systemd uses 'targets' instead of runlevels. By default, there are two main targets:
#
# multi-user.target: analogous to runlevel 3
# graphical.target: analogous to runlevel 5
#
# To view current default target, run:
# systemctl get-default
#
# To set a default target, run:
# systemctl set-default TARGET.target
#

4、过滤出不以#号开头的行,并把空行去掉

[root@localhost tmp]# grep -v '^#' /etc/crontab
SHELL=/bin/bash
PATH=/sbin:/bin:/usr/sbin:/usr/bin
MAILTO=root



[root@localhost tmp]# grep -v '^#' /etc/crontab|grep -v '^$'
SHELL=/bin/bash
PATH=/sbin:/bin:/usr/sbin:/usr/bin
MAILTO=root

5、过滤任意一个字符与重复字符

[root@localhost tmp]# grep 'r.o' test.txt
root:x:0:0:root:/root:/bin/bash
operator:x:11:0:operator:/root:/sbin/nologin

[root@localhost tmp]# grep 'o*t' test.txt                           #表示出现了零次或者多次o后面是t的字符
root:x:0:0:root:/root:/bin/bash
shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
halt:x:7:0:halt:/sbin:/sbin/halt
operator:x:11:0:operator:/root:/sbin/nologin
ftp:x:14:50:FTP User:/var/ftp:/sbin/nologin
systemd-network:x:192:192:systemd Network Management:/:/sbin/nologin
dbus:x:81:81:System message bus:/:/sbin/nologin
polkitd:x:999:997:User for polkitd:/:/sbin/nologin
postfix:x:89:89::/var/spool/postfix:/sbin/nologin
sshd:x:74:74:Privilege-separated SSH:/var/empty/sshd:/sbin/nologin
tcpdump:x:72:72::/:/sbin/nologin
saslauth:x:997:76:Saslauthd user:/run/saslauthd:/sbin/nologin
ROot/ROOT/

6、过滤字符指定出现的次数

[root@localhost tmp]# grep 'o\{2\}' test.txt                                 #o\{2\}这里表示o出现2次,也可以是一个范围\{2,5\}表示出现2到5次
root:x:0:0:root:/root:/bin/bash
lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
mail:x:8:12:mail:/var/spool/mail:/sbin/nologin
operator:x:11:0:operator:/root:/sbin/nologin
postfix:x:89:89::/var/spool/postfix:/sbin/nologin
mailnull:x:47:47::/var/spool/mqueue:/sbin/nologin
smmsp:x:51:51::/var/spool/mqueue:/sbin/nologin

egrep应用 egrep 'o{2}'=grep -E 'o {2}' = grep 'o\ {2\ }'

[root@localhost tmp]# egrep 'o{2}' test.txt
root:x:0:0:root:/root:/bin/bash
lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
mail:x:8:12:mail:/var/spool/mail:/sbin/nologin
operator:x:11:0:operator:/root:/sbin/nologin
postfix:x:89:89::/var/spool/postfix:/sbin/nologin
mailnull:x:47:47::/var/spool/mqueue:/sbin/nologin
smmsp:x:51:51::/var/spool/mqueue:/sbin/nologin

[root@localhost tmp]# grep -E 'o{2}' test.txt
root:x:0:0:root:/root:/bin/bash
lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
mail:x:8:12:mail:/var/spool/mail:/sbin/nologin
operator:x:11:0:operator:/root:/sbin/nologin
postfix:x:89:89::/var/spool/postfix:/sbin/nologin
mailnull:x:47:47::/var/spool/mqueue:/sbin/nologin
smmsp:x:51:51::/var/spool/mqueue:/sbin/nologin

egrep 'oo+' 表示oo出现1到或者多次

[root@localhost tmp]# egrep 'oo+' test.txt
root:x:0:0:root:/root:/bin/bash
lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
mail:x:8:12:mail:/var/spool/mail:/sbin/nologin
operator:x:11:0:operator:/root:/sbin/nologin
postfix:x:89:89::/var/spool/postfix:/sbin/nologin
mailnull:x:47:47::/var/spool/mqueue:/sbin/nologin
smmsp:x:51:51::/var/spool/mqueue:/sbin/nologin

egrep 'root|luo' test.txt表示匹配root或者luo所有的行,|表示或者

[root@localhost tmp]# egrep 'root|luo' test.txt
root:x:0:0:root:/root:/bin/bash
operator:x:11:0:operator:/root:/sbin/nologin
luo:x:1001:1006::/home/luo:/bin/bash

扩展: 过滤一个目录下所有某类型文档中含有某字符的行:

[root@localhost tmp]# grep -r "--include=*.txt" 'root'  ./
./test.txt:root:x:0:0:root:/root:/bin/bash
./test.txt:operator:x:11:0:operator:/root:/sbin/nologin
./grep/test1.txt:root:x:0:0:root:/root:/bin/bash
./grep/test1.txt:operator:x:11:0:operator:/root:/sbin/nologin

说明: 过滤当前目录下所有.txt文件中含有字符串root的行

9.3sed工具

sed常用来打印某行或者查找替换 常用选项: -n 仅显示处理后的结果 -r 去义,不用再另外脱义 -e可以多个行为一起处理 -i直接修改文件 1、打印某行,打印行为要配合-n选项使用

[root@localhost tmp]# sed -n '3'p test.txt
bin:x:1:1:bin:/bin:/sbin/nologin

把第一行到最后一行打印出来

[root@localhost tmp]# sed -n '1,$'p test.txt
root:x:0:0:root:/root:/bin/bash
yy:iji#adklfjdl@fkjdkl?jfdkjk
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:997:User for polkitd:/:/sbin/nologin
postfix:x:89:89::/var/spool/postfix:/sbin/nologin
sshd:x:74:74:Privilege-separated SSH:/var/empty/sshd:/sbin/nologin
chrony:x:998:996::/var/lib/chrony:/sbin/nologin
rpc:x:32:32:Rpcbind Daemon:/var/lib/rpcbind:/sbin/nologin
rpcuser:x:29:29:RPC Service User:/var/lib/nfs:/sbin/nologin
tcpdump:x:72:72::/:/sbin/nologin
luo:x:1001:1006::/home/luo:/bin/bash
saslauth:x:997:76:Saslauthd user:/run/saslauthd:/sbin/nologin
mailnull:x:47:47::/var/spool/mqueue:/sbin/nologin
smmsp:x:51:51::/var/spool/mqueue:/sbin/nologin
nginx:x:996:995:Nginx web server:/var/lib/nginx:/sbin/nologin
mysql:x:1002:1002::/home/mysql:/sbin/nologin
ROot/ROOT/
3453535

指定打印的区间:

[root@localhost tmp]# sed -n '1,3'p test.txt
root:x:0:0:root:/root:/bin/bash
yy:iji#adklfjdl@fkjdkl?jfdkjk
bin:x:1:1:bin:/bin:/sbin/nologin

2、打印包含某个字符串的行

[root@localhost tmp]# sed -n '/root/'p test.txt                           #匹配字符串的时候两边要加上//
root:x:0:0:root:/root:/bin/bash
operator:x:11:0:operator:/root:/sbin/nologin

打印一个区间内包含字符串的行

[root@localhost tmp]# sed -n '1,10{/root/p}' test.txt
root:x:0:0:root:/root:/bin/bash

3、删除某行或者多行 sed 删除不用配合-n使用

[root@localhost tmp]# sed '1'd test.txt                     ##删除第一行,把剩下的显示出来
yy:iji#adklfjdl@fkjdkl?jfdkjk
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@localhost tmp]# sed '1,3'd test.txt                     ###删除第一行到第三行,把剩下的显示出来
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
...

[root@localhost tmp]# sed '/root/'d test.txt                 ###删除包含root的行,把剩下的显示出来
yy:iji#adklfjdl@fkjdkl?jfdkjk
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
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
...

4、替换字符或字符串 ‘s’ 就是替换的命令, ‘g’ 为本行中全局替换,如果不加 ‘g’ 只换该行中出现的第一个。除了可以使用 ‘/’ 作为分隔符外,还可以使用其他特殊字符例如 ‘#’ 或者 ‘@’ 都没有问题。

[root@localhost tmp]# sed 's/root/toor/g' test.txt                     #把所有行的root替换成toor
toor:x:0:0:toor:/toor:/bin/bash
yy:iji#adklfjdl@fkjdkl?jfdkjk
bin:x:1:1:bin:/bin:/sbin/nologin
operator:x:11:0:operator:/toor:/sbin/nologin
...

指定替换的区间

[root@localhost tmp]# sed '1,3 s/root/toor/g' test.txt                #把1到3行的root替换成toor,如果是1到最后一行'1,$'
toor:x:0:0:toor:/toor:/bin/bash
yy:iji#adklfjdl@fkjdkl?jfdkjk
bin:x:1:1:bin:/bin:/sbin/nologin
...

把所有的数字替换成空,即去除所有的数字

[root@localhost tmp]# sed 's/[0-9]//g' test.txt
root:x:::root:/root:/bin/bash
yy:iji#adklfjdl@fkjdkl?jfdkjk
bin:x:::bin:/bin:/sbin/nologin
daemon:x:::daemon:/sbin:/sbin/nologin
adm:x:::adm:/var/adm:/sbin/nologin
lp:x:::lp:/var/spool/lpd:/sbin/nologin
sync:x:::sync:/sbin:/bin/sync
shutdown:x:::shutdown:/sbin:/sbin/shutdown
halt:x:::halt:/sbin:/sbin/halt
mail:x:::mail:/var/spool/mail:/sbin/nologin
operator:x:::operator:/root:/sbin/nologin
games:x:::games:/usr/games:/sbin/nologin
ftp:x:::FTP User:/var/ftp:/sbin/nologin
nobody:x:::Nobody:/:/sbin/nologin
systemd-network:x:::systemd Network Management:/:/sbin/nologin
dbus:x:::System message bus:/:/sbin/nologin
polkitd:x:::User for polkitd:/:/sbin/nologin
postfix:x::::/var/spool/postfix:/sbin/nologin
sshd:x:::Privilege-separated SSH:/var/empty/sshd:/sbin/nologin
chrony:x::::/var/lib/chrony:/sbin/nologin
rpc:x:::Rpcbind Daemon:/var/lib/rpcbind:/sbin/nologin
rpcuser:x:::RPC Service User:/var/lib/nfs:/sbin/nologin
tcpdump:x::::/:/sbin/nologin
luo:x::::/home/luo:/bin/bash
saslauth:x:::Saslauthd user:/run/saslauthd:/sbin/nologin
mailnull:x::::/var/spool/mqueue:/sbin/nologin
smmsp:x::::/var/spool/mqueue:/sbin/nologin
nginx:x:::Nginx web server:/var/lib/nginx:/sbin/nologin
mysql:x::::/home/mysql:/sbin/nologin
ROot/ROOT/

5、调换两个字符串的位置

[root@localhost tmp]# sed -r 's/(root)(.*)(bash)/\3\2\1/' test.txt
bash:x:0:0:root:/root:/bin/root
...

说明:用 () 把所想要替换的字符括起来成为一个整体,因为括号在sed中属于特殊符号,所以需要在前面加脱意字符 ,也可以使用sed -r 替换时则写成 ‘1’, ‘‘2’, ‘‘3’ 的形式 6、在某一行前或者后增加指定内容

[root@localhost tmp]# sed '1,2 s/^.*$/& 333/g' test.txt          ##在1,2行的后面加上空格333
root:x:0:0:root:/root:/bin/bash 333
yy:iji#adklfjdl@fkjdkl?jfdkjk 333


[root@localhost tmp]# sed '1,2 s/^.*$/333 &/g' test.txt             ## ##在1,2行的前面加上333空格
333 root:x:0:0:root:/root:/bin/bash
333 yy:iji#adklfjdl@fkjdkl?jfdkjk

7、直接修改文件的内容

[root@localhost tmp]# sed -i 's/root/toor/' test.txt           #没有任何输出,直接修改文件 内容
[root@localhost tmp]# cat test.txt 
toor:x:0:0:root:/root:/bin/bash
...

9.4awk工具

awk和sed一样是流式编辑器,它也是针对文档中的行来操作的,一行一行的去执行 awk语法结构: awk -F ':' 'BEGIN{语句} {if(条件){语句1;语句2;语句3} } END{语句}' filename FS指定分隔符 也可以使用-F指定 OFS指定输出的分隔符 NR行号 NF段号$NF表示最后一段 $0表示整行 $1表示第1段,依次类推$2表示第2段 $3... 1、截取文档中的某个段

[root@localhost tmp]# awk -F":" '{print $1}' test.txt 
toor
yy
bin
daemon
adm
lp
sync
shutdown
halt
mail
operator
games

2、打印自定义的内容,自定义的内容要用双引号引起来

[root@localhost tmp]# awk -F':' '{print $1"#"$2"#"$3}' test.txt 
toor#x#0
yy#iji#adklfjdl@fkjdkl?jfdkjk#
bin#x#1
daemon#x#2
adm#x#3
lp#x#4

3、定义输出分隔符

[root@localhost tmp]# awk -F':' ' OFS="@" {print $1,$2,$3}' test.txt 
toor@x@0
yy@iji#adklfjdl@fkjdkl?jfdkjk@
bin@x@1
daemon@x@2
adm@x@3
lp@x@4

4、使用多个分隔符

[root@localhost tmp]# cat 1.txt
zhang:460 luo:560                                         #这里我们想打印460和560可以使用多个分隔符
[root@localhost tmp]# awk -F ":| " '{print $2,$4}' 1.txt          #把冒号和空格都当作分隔符来使用
460 560

5、匹配字符或字符串

[root@localhost tmp]# awk '/root/' test.txt                      #这里和sed一样匹配字符串的时候两边要加上//
toor:x:0:0:root:/root:/bin/bash

指定哪段匹配

[root@localhost tmp]# awk -F ":" '$1~/toor/' test.txt
toor:x:0:0:root:/root:/bin/bash

6、条件操作 awk中是可以用逻辑符号判断的,比如 ‘==’ 就是等于,也可以理解为 ‘精确匹配’ 另外也有 >, ‘>=, ‘<, ‘<=, ‘!= 等等,值得注意的是,在和数字比较时,若把比较的数字用双引号引起来后,那么awk不会认为是数字,而认为是字符,不加双引号则认为是数字

[root@localhost tmp]# awk -F ':' '$3==0' test.txt                   #把第三段等于0的匹配出来
toor:x:0:0:root:/root:/bin/bash

[root@localhost tmp]# awk -F":" '$1="aaa"' test.txt               #给第一段赋值,字符串要用双引号引起来
aaa x 0 0 root /root /bin/bash
aaa iji#adklfjdl@fkjdkl?jfdkjk
aaa x 1 1 bin /bin /sbin/nologin
aaa x 2 2 daemon /sbin /sbin/nologin
aaa x 3 4 adm /var/adm /sbin/nologin

[root@localhost tmp]# awk -F':' '$3<1' test.txt                #把第三段小于1的匹配出来
toor:x:0:0:root:/root:/bin/bash
yy:iji#adklfjdl@fkjdkl?jfdkjk
ROot/ROOT/

&& 表示 “并且”

 [root@localhost ~]# awk -F ':' '$3>"5" && $3<"7"' /etc/passwd
shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
vcsa:x:69:69:virtual console memory owner:/dev:/sbin/nologin
haldaemon:x:68:68:HAL daemon:/:/sbin/nologin
user11:x:510:502:user11,user11's office,12345678,123456789:/home/user11:/sbin/nologin
test:x:511:511::/home/test:/bin/bash
test1:x:512:511::/home/test1:/bin/bash

||表示或者

[root@localhost ~]# awk -F ':' '$3>"5" || $7=="/bin/bash"' /etc/passwd
root:x:0:0:root:/root:/bin/bash
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
nobody:x:99:99:Nobody:/:/sbin/nologin
dbus:x:81:81:System message bus:/:/sbin/nologin
vcsa:x:69:69:virtual console memory owner:/dev:/sbin/nologin
haldaemon:x:68:68:HAL daemon:/:/sbin/nologin
postfix:x:89:89::/var/spool/postfix:/sbin/nologin
sshd:x:74:74:Privilege-separated SSH:/var/empty/sshd:/sbin/nologin
tcpdump:x:72:72::/:/sbin/nologin
user11:x:510:502:user11,user11's office,12345678,123456789:/home/user11:/sbin/nologin
test:x:511:511::/home/test:/bin/bash
test1:x:512:511::/home/test1:/bin/bash

7、打印段数或者行号

[root@localhost tmp]# awk -F':' '{print NF}' test.txt|head -3                     #显示前三行的段数
7
2
7

[root@localhost tmp]# awk -F':' '{print $NF}' test.txt                         #打印最后一段
/bin/bash
iji#adklfjdl@fkjdkl?jfdkjk
/sbin/nologin
/sbin/nologin
/sbin/nologin
/sbin/nologin
/bin/sync
/sbin/shutdown
...

[root@localhost tmp]# awk '{print NR}' test.txt                                  #打印行号
1
2
3
4
5
6
7
8
9
10
...

8、计算某个段的总和

[root@localhost tmp]# awk -F':' '{(sum=sum+$3)} END{print sum}' test.txt 
6832
也可以写成这样
[root@localhost tmp]# awk -F':' '{(sum+=$3)} END{print sum}' test.txt 
6832

9、if判断

[root@localhost tmp]# awk -F':' '{if($3==0) print $1}' test.txt 
toor