第十一章:正则表达式
一、grep/egrep工具的使用
格式:grep 【-cinvABC】 ‘关键词’ filename。
- -c:不是打印符合要求的行数;
- -i:表示忽略大小写;
- -n:表示输出符合要求的行及其行号;
- -v:表示打印不符合要求的行;
- -A:后面跟一个数字(有无空格都可以),例如-A2表示打印符合要求的行以及下面两行;
- -B:后面跟一个数字,例如-B2表示打印符合要求的行以及上面两行;
- -C:后面跟一个数字,例如-C2表示打印符合要求的行以及上下两行。
下面是对于-A2、-B2、-C2用法的演示:
[root@zl_cloud ~]# grep -A2 'halt' /etc/passwd
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@zl_cloud ~]#
[root@zl_cloud ~]# grep -B2 'halt' /etc/passwd
sync:x:5:0:sync:/sbin:/bin/sync
shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
halt:x:7:0:halt:/sbin:/sbin/halt
[root@zl_cloud ~]#
[root@zl_cloud ~]# grep -C2 'halt' /etc/passwd
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@zl_cloud ~]#
1.过滤处带有某个关键词的行,并输出行号
格式:grep -n ‘关键词’ 【文件】
[root@zl_cloud ~]# grep -n 'root' /etc/passwd //前面数字为行号
1:root:x:0:0:root:/root:/bin/bash
10:operator:x:11:0:operator:/root:/sbin/nologin
[root@zl_cloud ~]#
2.过滤处不带有某个关键词的行,并输出行号
格式:grep -nv ‘关键词’ 【文件】
[root@zl_cloud ~]# grep -nv 'nologin' /etc/passwd
1:root:x:0:0:root:/root:/bin/bash
6:sync:x:5:0:sync:/sbin:/bin/sync
7:shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
8:halt:x:7:0:halt:/sbin:/sbin/halt
22:user1:x:1000:1000::/home/user1:/bin/bash
23:usertest:x:1001:1002::/home/usertest:/bin/bash
24:usertest1:x:1003:1002:usertest1,1,1,1:/home/usertest1:/bin/bash
25:test:x:1004:1004::/home/test:/bin/bash
26:zl:x:1005:1005::/home/zl:/bin/bash
[root@zl_cloud ~]#
3.过滤出所有包含数字的行
格式:grep ‘[数字范围]’ 【文件】
[root@zl_cloud ~]# grep '[0-9]' /etc/inittab
# multi-user.target: analogous to runlevel 3
# graphical.target: analogous to runlevel 5
[root@zl_cloud ~]#
4.过滤出所有不包含数字的行
格式:grep -v ‘[数字范围]’ 【文件】
[root@zl_cloud ~]# grep -v '[0-9]' /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:
#
#
# To view current default target, run:
# systemctl get-default
#
# To set a default target, run:
# systemctl set-default TARGET.target
#
[root@zl_cloud ~]#
5.过滤掉所有以#开头的行
格式:grep -v '^#'【文件】
[root@zl_cloud ~]# cat 1.txt //源文件
TEST
aaaaaaa
#111
#222
111
222
[root@zl_cloud ~]# grep -v '^#' 1.txt //过滤后,它是包含空行的
TEST
aaaaaaa
111
222
[root@zl_cloud ~]#
6.过滤掉所有空行和以#开头的行
格式:grep -v '^#' 【文件】 | grep -v ‘^$’
[root@zl_cloud ~]# grep -v '^#' 1.txt | grep -v '^$'
TEST
aaaaaaa
111
222
[root@zl_cloud ~]#
如何打印出不以英文字母开头的行呢:
格式:grep '^[^a-zA-Z]'【文件】
[root@zl_cloud ~]# cat 1.txt
TEST
123
abc
456
abc222
#hjftdug
Afdhg
[root@zl_cloud ~]# grep '^[^a-zA-Z]' 1.txt //除字母开头
123
456
#hjftdug
[root@zl_cloud ~]# grep '[^a-zA-Z]' 1.txt
123
456
abc222
#hjftdug
[root@zl_cloud ~]#
[^字符]表示除[ ]内字符之外的字符,在正则表达式中,^表示行的开始,$表示行的结尾。
7.过滤出任意一个字符和重复字符
格式:grep '字符.字符' filename
[root@zl_cloud ~]# grep 'r.o' /etc/passwd
root:x:0:0:root:/root:/bin/bash
operator:x:11:0:operator:/root:/sbin/nologin
[root@zl_cloud ~]#
.表示任意一个字符
[root@zl_cloud ~]# grep 'ooo*' /etc/passwd
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
[root@zl_cloud ~]#
*
表示零个或多个*
前面的字符。ooo*表示oo、ooo、oooo…或者更多的o
[root@zl_cloud ~]# grep '.*' /etc/passwd | wc -l
26
[root@zl_cloud ~]#
.*
表示零个或多个任意字符,空行也包含在内。
[root@zl_cloud ~]# wc -l /etc/passwd
26 /etc/passwd
[root@zl_cloud ~]#
8.指定要过滤出的字符出现次数
格式:grep '字符\{数字\}' filename
[root@zl_cloud ~]# grep 'o\{2\}' /etc/passwd
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
[root@zl_cloud ~]#
这里用到了符号{ },其内部为数字,表示前面的字符要重复的次数。需要强调的是,{ }左右都需要加上转义字符。另使用{ }时还可以表示一个范围,具体格式为{n1,n2},n2还可以为空,这时表示大于等于n1次。
egrep时grep的扩展版本,可以完成grep不能完成的工作。先编辑一个这样的内容文件方便实验:
[root@zl_cloud ~]# cat test.txt
rot:x:0:0:/rot:/bin/bash
operator:x:11:0:operator:/root:/sbin/nologin
operator:x:11:0:operator:/rooot:/sbin/nologin
roooot:x:0:0:/rooooot:/bin/bash
1111111111111111111111111111111
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
[root@zl_cloud ~]#
9.过滤处一个或多个指定的字符
格式:grep '字符+' filename
[root@zl_cloud ~]# egrep 'o+' test.txt
rot:x:0:0:/rot:/bin/bash
operator:x:11:0:operator:/root:/sbin/nologin
operator:x:11:0:operator:/rooot:/sbin/nologin
roooot:x:0:0:/rooooot:/bin/bash
[root@zl_cloud ~]# egrep 'oo+' test.txt
operator:x:11:0:operator:/root:/sbin/nologin
operator:x:11:0:operator:/rooot:/sbin/nologin
roooot:x:0:0:/rooooot:/bin/bash
[root@zl_cloud ~]# egrep 'ooo+' test.txt
operator:x:11:0:operator:/rooot:/sbin/nologin
roooot:x:0:0:/rooooot:/bin/bash
[root@zl_cloud ~]#
和grep不同,这里使用的时符号+,他表示匹配1个或多个前面的字符。{ }符号可以直接被egrep使用,而不用加\转义:
[root@zl_cloud ~]# egrep 'o{2}' /etc/passwd
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
[root@zl_cloud ~]#
10.过滤处零个或一个指定的字符
格式:egrep '字符?' filename
[root@zl_cloud ~]# egrep 'o?' test.txt
rot:x:0:0:/rot:/bin/bash
operator:x:11:0:operator:/root:/sbin/nologin
operator:x:11:0:operator:/rooot:/sbin/nologin
roooot:x:0:0:/rooooot:/bin/bash
1111111111111111111111111111111
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
[root@zl_cloud ~]# egrep 'ooo?' test.txt
operator:x:11:0:operator:/root:/sbin/nologin
operator:x:11:0:operator:/rooot:/sbin/nologin
roooot:x:0:0:/rooooot:/bin/bash
[root@zl_cloud ~]# egrep 'oooo?' test.txt
operator:x:11:0:operator:/rooot:/sbin/nologin
roooot:x:0:0:/rooooot:/bin/bash
[root@zl_cloud ~]#
11.过滤处字符串1或者字符串2
格式:egrep '字符|字符|字符' filename
[root@zl_cloud ~]# egrep 'aaa|111|ooo' test.txt
operator:x:11:0:operator:/rooot:/sbin/nologin
roooot:x:0:0:/rooooot:/bin/bash
1111111111111111111111111111111
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
[root@zl_cloud ~]#
12.egrep中()的应用
格式:egrep '字符(字符|字符)字符' filename
[root@zl_cloud ~]# egrep 'r(oo|at)o' test.txt
operator:x:11:0:operator:/root:/sbin/nologin
operator:x:11:0:operator:/rooot:/sbin/nologin
roooot:x:0:0:/rooooot:/bin/bash
[root@zl_cloud ~]#
这里用()表示一个整体,上例会把包含root或者rato的行过滤出来,另外也可以()和其他字符组合在一起,例如(oo)+就表示1个或者多个oo:
[root@zl_cloud ~]# egrep '(oo)+' test.txt
operator:x:11:0:operator:/root:/sbin/nologin
operator:x:11:0:operator:/rooot:/sbin/nologin
roooot:x:0:0:/rooooot:/bin/bash
[root@zl_cloud ~]#
二、sed工具的使用
1.打印某行
格式:sed -n ‘n’p filename
,单引号内的n是一个数字,表示第几行。-n选项的作用是只显示我们要打印的行,无关紧要的内容不显示。
[root@zl_cloud ~]# sed -n '2'p /etc/passwd
bin:x:1:1:bin:/bin:/sbin/nologin
[root@zl_cloud ~]#
你可以去掉-n选项对比一下差异。要想把所有行都打印出来,可以使用使用命令sed -n ’1,$’p filename。(其实我去掉了-n后发现也就是把文件内容全打印出来了,跟这个内容是一样的。个人觉得cat不是更好嘛)
[root@zl_cloud ~]# sed -n '1,$'p test.txt
rot:x:0:0:/rot:/bin/bash
operator:x:11:0:operator:/root:/sbin/nologin
operator:x:11:0:operator:/rooot:/sbin/nologin
roooot:x:0:0:/rooooot:/bin/bash
1111111111111111111111111111111
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
[root@zl_cloud ~]#
[root@zl_cloud ~]# sed -n '1,3'p test.txt
rot:x:0:0:/rot:/bin/bash
operator:x:11:0:operator:/root:/sbin/nologin
operator:x:11:0:operator:/rooot:/sbin/nologin
[root@zl_cloud ~]#
2.打印包含某个字符串的行
格式:sed -n ‘/字符串/’p filename
[root@zl_cloud ~]# sed -n '/root/'p test.txt
operator:x:11:0:operator:/root:/sbin/nologin
[root@zl_cloud ~]#
这种用法就类似于grep了,在grep中使用的特殊字符(如^
、$
、.
、*
等)同样也能在sed中使用:
[root@zl_cloud ~]# sed -n '/^1/'p test.txt
1111111111111111111111111111111
[root@zl_cloud ~]# sed -n '/in$/'p test.txt
operator:x:11:0:operator:/root:/sbin/nologin
operator:x:11:0:operator:/rooot:/sbin/nologin
[root@zl_cloud ~]# sed -n '/r..o/'p test.txt
operator:x:11:0:operator:/root:/sbin/nologin
operator:x:11:0:operator:/rooot:/sbin/nologin
roooot:x:0:0:/rooooot:/bin/bash
[root@zl_cloud ~]# sed -n '/ooo*/'p test.txt
operator:x:11:0:operator:/root:/sbin/nologin
operator:x:11:0:operator:/rooot:/sbin/nologin
roooot:x:0:0:/rooooot:/bin/bash
[root@zl_cloud ~]#
sed命令加上-e选项可以实现多个行为:
[root@zl_cloud ~]# sed -e '1'p -e '/111/'p -n test.txt
rot:x:0:0:/rot:/bin/bash
1111111111111111111111111111111
[root@zl_cloud ~]#
3.删除某些行
删除指定单行:
格式:sed ‘n’d filename
[root@zl_cloud ~]# sed '1'd test.txt
operator:x:11:0:operator:/root:/sbin/nologin
operator:x:11:0:operator:/rooot:/sbin/nologin
roooot:x:0:0:/rooooot:/bin/bash
1111111111111111111111111111111
Aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
删除指定多行:
格式:sed ‘n1,n2’p filename
[root@zl_cloud ~]# sed '1,3'd test.txt
roooot:x:0:0:/rooooot:/bin/bash
1111111111111111111111111111111
Aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
删除匹配某个字符的行:
格式:sed ‘/字符串/’d filename
[root@zl_cloud ~]# sed '/oot/'d test.txt
rot:x:0:0:/rot:/bin/bash
1111111111111111111111111111111
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
[root@zl_cloud ~]#
这些操作仅仅是在显示器屏幕上不显示这些行而已,并不是真的删除文档。
4.替换字符或者字符串
格式:sed ‘n1,n2s/字符串/字符串/g’ filename
[root@zl_cloud ~]# sed '1,2s/ot/to/g' test.txt
rto:x:0:0:/rto:/bin/bash
operator:x:11:0:operator:/roto:/sbin/nologin
operator:x:11:0:operator:/rooot:/sbin/nologin
roooot:x:0:0:/rooooot:/bin/bash
1111111111111111111111111111111
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
[root@zl_cloud ~]#
参数s代表替换动作,参数g表示本行全局替换,如果不加g则只替换本行出现的第一个,跟vi的替换差不多。
除了可以使用/作为分隔符外,还可以使用其他特殊字符,例如#和@:
[root@zl_cloud ~]# sed 's#ot#to#g' test.txt
rto:x:0:0:/rto:/bin/bash
operator:x:11:0:operator:/roto:/sbin/nologin
operator:x:11:0:operator:/rooto:/sbin/nologin
roooto:x:0:0:/rooooto:/bin/bash
1111111111111111111111111111111
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
[root@zl_cloud ~]# sed 's@ot@to@g' test.txt
rto:x:0:0:/rto:/bin/bash
operator:x:11:0:operator:/roto:/sbin/nologin
operator:x:11:0:operator:/rooto:/sbin/nologin
roooto:x:0:0:/rooooto:/bin/bash
1111111111111111111111111111111
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
[root@zl_cloud ~]#
如何让删除文档中所有的数字或者字母?命令如下:
格式:sed ‘s/[n1-n2]//g’ filename
(这里是替换为空)
[root@zl_cloud ~]# sed 's/[0-9]//g' test.txt
rot:x:::/rot:/bin/bash
operator:x:::operator:/root:/sbin/nologin
operator:x:::operator:/rooot:/sbin/nologin
roooot:x:::/rooooot:/bin/bash
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
[root@zl_cloud ~]#
[0-9]表示任意的数字。也可以写成[a-zA-Z]或者[0-9a-zA-Z]:
格式:sed ‘s/[a-zA-Z]//g’ filename
(这里是替换为空)
[root@zl_cloud ~]# sed 's/[a-zA-Z]//g' test.txt
::0:0:/://
::11:0::/://
::11:0::/://
::0:0:/://
1111111111111111111111111111111
[root@zl_cloud ~]#
5.调换两个字符串的位置
格式:sed 's/\(字符串\)\(.*\)\(字符串\)/\3\2\1/’ filename
[root@zl_cloud ~]# sed 's/\(rot\)\(.*\)\(bash\)/\3\2\1/' test.txt
bash:x:0:0:/rot:/bin/rot
operator:x:11:0:operator:/root:/sbin/nologin
operator:x:11:0:operator:/rooot:/sbin/nologin
roooot:x:0:0:/rooooot:/bin/bash
1111111111111111111111111111111
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
[root@zl_cloud ~]#
小括号在sed中属于特殊符号,必须在前面加转义字符\,替换时则携程类似\、\2或\3的形式。括号只是想把替换的字符打包成一个整体。如何省略转义字符呢?加-r选项!
格式:sed -r 's/(字符串)(.*)(字符串)/\3\2\1/’ filename
[root@zl_cloud ~]# sed -r 's/(rot)(.*)(bash)/\3\2\1/' test.txt
bash:x:0:0:/rot:/bin/rot
operator:x:11:0:operator:/root:/sbin/nologin
operator:x:11:0:operator:/rooot:/sbin/nologin
roooot:x:0:0:/rooooot:/bin/bash
1111111111111111111111111111111
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
[root@zl_cloud ~]#
除了调换两个字符串的位置,有时候常常会用sed在某一行前后增加指定内容:
格式:sed 's/^.*$/指定内容$/’ filename
[root@zl_cloud ~]# sed 's/^.*$/123&/' test.txt
123rot:x:0:0:/rot:/bin/bash
123operator:x:11:0:operator:/root:/sbin/nologin
123operator:x:11:0:operator:/rooot:/sbin/nologin
123roooot:x:0:0:/rooooot:/bin/bash
1231111111111111111111111111111111
123aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
[root@zl_cloud ~]#
6.直接修改文件的内容
格式:sed -i 's/(字符串)/(字符串)/g’ filename
[root@zl_cloud ~]# sed -i 's/ot/to/g' test.txt
[root@zl_cloud ~]# cat test.txt
rto:x:0:0:/rto:/bin/bash
operator:x:11:0:operator:/roto:/sbin/nologin
operator:x:11:0:operator:/rooto:/sbin/nologin
roooto:x:0:0:/rooooto:/bin/bash
1111111111111111111111111111111
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
[root@zl_cloud ~]#
三、awk工具的使用
1.截取文档中的某个段
- -F:指定分隔符;(不加以空格或者tab为分隔符)
格式:awk -F ':' '{print 字段}'
[root@zl_cloud ~]# head -n2 test.txt | awk -F ':' '{print $1}' $1为第一个字段
rto
operator
[root@zl_cloud ~]#
[root@zl_cloud ~]# head -n2 test.txt | awk -F ':' '{print $0}' $0比较特殊,表示整行
rto:x:0:0:/rto:/bin/bash
operator:x:11:0:operator:/roto:/sbin/nologin
[root@zl_cloud ~]#
注意awk的格式,-F后面紧跟单引号,单引号里面为分隔符。print的动作要用{ }括起来,否则会报错。print还可以打印自定义内容,但是自定义内容要用双括号括起来:
格式:awk -F ':' '{print 字段 “自定义内容”}'
[root@zl_cloud ~]# head -n2 test.txt | awk -F ':' '{print $1"#""$2""#""$3""#""$4"}'
rto#$2#$3#$4
operator#$2#$3#$4
[root@zl_cloud ~]#
2.匹配字符或者字符串
格式:awk ‘/字符/’ filename
[root@zl_cloud ~]# awk '/oo/' test.txt
operator:x:11:0:operator:/rooto:/sbin/nologin
roooto:x:0:0:/rooooto:/bin/bash
root:x:0:0:root:/root:/bin/bash
lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
mail:x:8:12:mail:/vai/spool/inail:/sbin/nologin
operator:x:il:0:operator:/root:/sbin/nologin
Postfix:x:89:89::/var/spool/po$tfix:/sbin/nologin
setroubleshoot:x:992:990::/var/lib/setioubleshoot:/sbin/nologin
[root@zl_cloud ~]#
跟sed用法相似,能实现grep的功能。不过awk还有比sed更强大的匹配:
格式:awk -F ‘:’ ‘字段~/字符/’ filename
[root@zl_cloud ~]# awk -F ':' '$1~/oo/' test.txt
roooto:x:0:0:/rooooto:/bin/bash
root:x:0:0:root:/root:/bin/bash
setroubleshoot:x:992:990::/var/lib/setioubleshoot:/sbin/nologin
[root@zl_cloud ~]#
它可以让某个字段去匹配,~就是匹配的意思,并且awk可以多次匹配:
[root@zl_cloud ~]# awk -F ':' '/root/ {print $1,$3} /test/ {print $1,$3}' test.txt
operator 11
root 0
operator il
[root@zl_cloud ~]#
本例中awk匹配完root,再匹配test,还可以打印所匹配的段。
3.条件操作符
格式:awk -F ‘:’ ‘字段==“值”’ filename
[root@zl_cloud ~]# awk -F ':' '$3=="0"' /etc/passwd
root:x:0:0:root:/root:/bin/bash
[root@zl_cloud ~]#
可以用逻辑符号进行判断,比如==就是等于,也可以理解为精确匹配。另外还有>、>=、<、<=、!=等。值得注意的是在和数字比较时,若是把比较的数字用双引号引起来,那么awk不会认为是数字,而是认为是字符,不加双引号则会认为是数字。
格式:awk -F ‘:’ ‘字段>=“值”’ filename
[root@zl_cloud ~]# awk -F ':' '$3>="500"' /etc/passwd
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
systemd-bus-proxy:x:999:997:systemd Bus Proxy:/:/sbin/nologin
systemd-network:x:998:996:systemd Network Management:/:/sbin/nologin
dbus:x:81:81:System message bus:/:/sbin/nologin
polkitd:x:997:995:User for polkitd:/:/sbin/nologin
tss:x:59:59:Account used by the trousers package to sandbox the tcsd daemon:/dev/null:/sbin/nologin
postfix:x:89:89::/var/spool/postfix:/sbin/nologin
sshd:x:74:74:Privilege-separated SSH:/var/empty/sshd:/sbin/nologin
[root@zl_cloud ~]#
不加双引号后:(这个原理跟sort排序一样。)
格式:awk -F ‘:’ ‘字段>=值’ filename
[root@zl_cloud ~]# awk -F ':' '$3>=500' /etc/passwd
systemd-bus-proxy:x:999:997:systemd Bus Proxy:/:/sbin/nologin
systemd-network:x:998:996:systemd Network Management:/:/sbin/nologin
polkitd:x:997:995:User for polkitd:/:/sbin/nologin
user1:x:1000:1000::/home/user1:/bin/bash
usertest:x:1001:1002::/home/usertest:/bin/bash
usertest1:x:1003:1002:usertest1,1,1,1:/home/usertest1:/bin/bash
test:x:1004:1004::/home/test:/bin/bash
zl:x:1005:1005::/home/zl:/bin/bash
[root@zl_cloud ~]#
[root@zl_cloud ~]# awk -F ':' '$7!="/sbin/nologin"' /etc/passwd
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
user1:x:1000:1000::/home/user1:/bin/bash
usertest:x:1001:1002::/home/usertest:/bin/bash
usertest1:x:1003:1002:usertest1,1,1,1:/home/usertest1:/bin/bash
test:x:1004:1004::/home/test:/bin/bash
zl:x:1005:1005::/home/zl:/bin/bash
[root@zl_cloud ~]#
本例中,!=表示不匹配,他除了针对某一个段的字符进行逻辑比较外,还可以在两个段之间进行逻辑比较。
格式:awk -F ‘:’ ‘字段 比较符号 字段’ filename
[root@zl_cloud ~]# awk -F ':' '$3<$4' /etc/passwd
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
games:x:12:100:games:/usr/games:/sbin/nologin
ftp:x:14:50:FTP User:/var/ftp:/sbin/nologin
usertest:x:1001:1002::/home/usertest:/bin/bash
[root@zl_cloud ~]#
另外还可以使用&&和||,分别表示并且和或者:
[root@zl_cloud ~]# awk -F ':' '$3>"5" && $3<"7"' /etc/passwd
shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
tss:x:59:59:Account used by the trousers package to sandbox the tcsd daemon:/dev/null:/sbin/nologin
[root@zl_cloud ~]# awk -F ':' '$3>1000 || $7=="/bin/bash"' /etc/passwd
root:x:0:0:root:/root:/bin/bash
user1:x:1000:1000::/home/user1:/bin/bash
usertest:x:1001:1002::/home/usertest:/bin/bash
usertest1:x:1003:1002:usertest1,1,1,1:/home/usertest1:/bin/bash
test:x:1004:1004::/home/test:/bin/bash
zl:x:1005:1005::/home/zl:/bin/bash
[root@zl_cloud ~]#
4.awk的内置变量
awk常用的变量有OFS、NF和NR,OFS和-F选项有类似的功能,也是用来定义分隔符的,但是他是在输出的时候定义,NF表示用分隔符分隔后一共有多少段,NR表示行号。
①OFS(NR,OFS和-F选项有类似的功能,也是用来定义分隔符的,但是他是在输出的时候定义)
[root@zl_cloud ~]# head -5 /etc/passwd |awk -F ':' '{OFS="#"} {print $1,$3,$4}'
root#0#0
bin#1#1
daemon#2#2
adm#3#4
lp#4#7
[root@zl_cloud ~]#
[root@zl_cloud ~]# awk -F ':' '{OFS="#"} {if($3>1000) {print $1,$2,$3,$4}}' /etc/passwd
usertest#x#1001#1002
usertest1#x#1003#1002
test#x#1004#1004
zl#x#1005#1005
[root@zl_cloud ~]#
②NF(NF表示用分隔符分隔后一共有多少段。NF是多少段,$NF是最后一段的值)
[root@zl_cloud ~]# head -n3 /etc/passwd |awk -F ':' '{print NF}'
7
7
7
[root@zl_cloud ~]# head -n3 /etc/passwd |awk -F ':' '{print $NF}'
/bin/bash
/sbin/nologin
/sbin/nologin
[root@zl_cloud ~]#
③NR(NR表示行号。可做判断条件,也可以配合段匹配一起使用)
[root@zl_cloud ~]# head -n3 /etc/passwd |awk -F ':' '{print NR}'
1
2
3
[root@zl_cloud ~]#
[root@zl_cloud ~]# awk 'NR>40' /etc/passwd
...
[root@zl_cloud ~]#
[root@zl_cloud ~]# awk -F ':' 'NR<20 && $1 ~ /roo/' /etc/passwd
root:x:0:0:root:/root:/bin/bash
[root@zl_cloud ~]#
5.awk中的数学运算
①awk可以更改段值:
[root@zl_cloud ~]# head -n 3 /etc/passwd |awk -F ':' '$1="root"'
root x 0 0 root /root /bin/bash
root x 1 1 bin /bin /sbin/nologin
root x 2 2 daemon /sbin /sbin/nologin
[root@zl_cloud ~]#
②对各个段的值进行数学运算:
[root@zl_cloud ~]# head -n2 /etc/passwd
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
[root@zl_cloud ~]# head -n2 /etc/passwd | awk -F ‘:’ ‘{$7=$3+$4; print $0}’
root x 0 0 root /root 0
bin x 1 1 bin /bin 2
[root@zl_cloud ~]#
③计算某个段的总和:
[root@zl_cloud ~]# awk -F ':' '{(tot=tot+$3)};END {print tot}' /etc/passwd
8652
[root@zl_cloud ~]#
这里的END是awk特有的语法,表示所有的行都已经执行。
其实awk连同sed都可以写成一个脚本文件,而且有他们特有的语法。在awk中使用if判断,for循环都可以:
[root@zl_cloud ~]# awk -F ':' '{if ($1=="root") {print $0}}' /etc/passwd
root:x:0:0:root:/root:/bin/bash
[root@zl_cloud ~]#