正则表达式

2.正则表达式

定义:它使用单个字符串来描述或匹配一系列符合某个句法规则的字符串。在很多文本编辑器或其它工具中,正则表达式通常用来检索和替换某个模式的文本内容。

其实正则表达式只是一种思想、一种方法。只要我们使用的工具支持这种方法,那么这个工具就可以处理正则表达试的字符串。常用的工具有grep、sed、awk等,其中grep、sed和awk都是对文本的行进行操作。

2.1 grep/egrep工具的使用

该命令的格式为:grep [-cnvABC] 'worf' filename,其常用的选项如下所示:

-c:表示打印符合要求的行数。

-i:表示忽略大小写。

-n:表示输出符合要求的行机器行号。

-v:表示打印不符合要求的行。

-A:后面跟一个数字(有无空格都可以),例如-A2表示打印符合要求的行以及下面两行。

-B:后面跟一个数字,例如-B2表示打印符合要求的行以及上面两行。

-C:后面跟一个数字,例如-C2表示打印符合要求的行以及上下各两行。

首先看看-A、-B和-C这3个选项的用法。

-A2会把包含halt的行以及这行下面的两行都打印出来:

[root@localhost ~]# 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

-B2:会把包含halt的行以及这行上面的两行都打印出来:

[root@localhost ~]# 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

-C2会把包含halt的行以及上下各两行都打印出来:

[root@localhost ~]# 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

2.1.1过滤出带有某个关键词的行,并输出行号

示例命令如下:

[root@localhost ~]# grep -n 'root' /etc/passwd

1:root:x:0:0:root:/root:/bin/bash

10:operator:x:11:0:operator:/root:/sbin/nologin

2.1.2过滤出不带有某个关键词的行,并输出行号

示例命令如下:

[root@localhost ~]# grep -nv 'root' /etc/passwd

2:bin:x:1:1:bin:/bin:/sbin/nologin

3:daemon:x:2:2:daemon:/sbin:/sbin/nologin

4:adm:x:3:4:adm:/var/adm:/sbin/nologin

5:lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin

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

9:mail:x:8:12:mail:/var/spool/mail:/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

14:systemd-network:x:192:192:systemd Network Management:/:/sbin/nologin

15:dbus:x:81:81:System message bus:/:/sbin/nologin

16:polkitd:x:999:998:User for polkitd:/:/sbin/nologin

17:sshd:x:74:74:Privilege-separated SSH:/var/empty/sshd:/sbin/nologin

18:postfix:x:89:89::/var/spool/postfix:/sbin/nologin

19:chrony:x:998:996::/var/lib/chrony:/sbin/nologin

2.1.3过滤出包含数字的行

示例命令如下:

[root@localhost ~]# grep '[0-9]' /etc/inittab

multi-user.target: analogous to runlevel 3

graphical.target: analogous to runlevel 5

2.1.4过滤出所有不包含数字的行

[root@localhost ~]# 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

2.1.5过滤掉所有空行和以#开头的行

示例命令如下:

[root@localhost ~]# cat /etc/grep.txt

aaaa

bbb

#ccc

dddd

[root@localhost ~]# grep -v '^#' /etc/grep.txt |grep -v '^$'

aaaa

bbb

dddd

正则表达式中,^表示行的开始,表示行的结尾,那么空行就可以用\^表示。如何打印出不以英文字母开头的行呢?举个例子:

[root@localhost ~]# cat /etc/grep.txt

2aaaa

b1bb

123

#ccc

2222

dddd

AAAAA

333

[root@localhost ~]# grep -v '^[a-zA-Z]' /etc/grep.txt

2aaaa

123

#ccc

2222

333

[root@localhost ~]# grep '^[^a-zA-Z]' /etc/grep.txt

2aaaa

123

#ccc

2222

333

[root@localhost ~]# grep '[^a-zA-Z]' /etc/grep.txt

2aaaa

b1bb

123

#ccc

2222

333

[^字符]表示除[]以外的字符。注意把^写到括号里跟括号外是有区别的。前面提到过[]的应用,如果是数字就用[0-9]这样的形式(当遇到类似[15]的形式时表示只含有1或者5)。如果要过滤数字以及大小写字母,则要写成类似[0-9a-zA-Z]的形式。

2.1.6过滤出任意一个字符和重复字符

示例命令如下:

[root@localhost ~]# grep 'r.o' /etc/passwd

root:x:0:0:root:/root:/bin/bash

operator:x:11:0:operator:/root:/sbin/nologin

.表示任意一个字符。上海李忠,r.o表示把r与o之间有一个任意字符的行过滤出来。

[root@localhost ~]# 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

*表示零个或多个*前面的字符。上例中,ooo*表示oo、ooo、oooo或者更多的o。

[root@localhost ~]# grep '.*' /etc/passwd |wc -l

19

*表示零个或者多个任意字符,空行也包括在内,他会把/etc/passwd文件里面所有行都匹配到。

2.1.7指定要过滤出的字符出现次数

示例命令如下:

[root@localhost ~]# grep '0\{2\}' /etc/passwd

games:x:12:100:games:/usr/games:/sbin/nologin

这里用到了符号{},其内部位数字,表示前面的字符要重复的次数。需要强调的是,{}左右都需要加上转义字符\。另外,使用"{}"还可以表示一个范围,具体格式{n1,n2},其中n1<n2,表示重复n1到n2次前面的字符,n2还可以为空,这是表示大于等于n1次。

除grep工具外,还有egrep这个工具,后者是前者的扩展版本,可以完成grep不能完成的工作。下面介绍下不同的用法为了实验方便,把grep.txt编辑成了如下内容:

[root@localhost ~]# vi /etc/grep.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

2.1.8过滤出一个或多个指定的字符

示例命令如下:

[root@localhost ~]# egrep 'o+' /etc/grep.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@localhost ~]# egrep 'oo+' /etc/grep.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@localhost ~]# egrep 'ooo+' /etc/grep.txt

operator:x:11:0:operator:/rooot:/sbin/nologin

roooot:x:0:0:/rooooot:/bin/bash

和grep不同的是,egrep使用的是符号+,他表示匹配1个或多个+前面的字符,这个"+"是不支持被grep直接使用的。包括上面的{},也是可以直接被egrep使用,而不用加\转义。示例如下:

[root@localhost ~]# egrep 'o{2}' /etc/grep.txt

operator:x:11:0:operator:/root:/sbin/nologin

operator:x:11:0:operator:/rooot:/sbin/nologin

roooot:x:0:0:/rooooot:/bin/bash

2.1.9过滤出零个或一个指定字符

示例如下:

[root@localhost ~]# egrep 'o?' /etc/grep.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@localhost ~]# egrep 'ooo?' /etc/grep.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@localhost ~]# egrep 'oooo?' /etc/grep.txt

operator:x:11:0:operator:/rooot:/sbin/nologin

roooot:x:0:0:/rooooot:/bin/bash

2.1.10过滤出字符串1或者字符串2

示例命令如下:

[root@localhost ~]# egrep 'aaa|111|ooo' /etc/grep.txt

operator:x:11:0:operator:/rooot:/sbin/nologin

roooot:x:0:0:/rooooot:/bin/bash

1111111111111111111111111111111

aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa

2.1.11egrep中()的应用

示例命令如下:

[root@localhost ~]# egrep 'r(oo|at)o' /etc/grep.txt

operator:x:11:0:operator:/root:/sbin/nologin

operator:x:11:0:operator:/rooot:/sbin/nologin

roooot:x:0:0:/rooooot:/bin/bash

这里用()表示一个整体,上例中会把包含rooo或者rato的行过滤出来,林外也可以吧()和其他符号组合在一起,例如(oo)+就表示1个或者多个oo。如下所示:

[root@localhost ~]# egrep '(oo)+' /etc/grep.txt

operator:x:11:0:operator:/root:/sbin/nologin

operator:x:11:0:operator:/rooot:/sbin/nologin

roooot:x:0:0:/rooooot:/bin/bash

2.2sed工具的使用

其实grep工具的功能还不够强大,它实现的只是查找功能,而不能把查找的能容替换。以前用vim操作文档的时候,可以查找也可以替换,但只限于在文本内部操作,而不能输出到屏幕上。sed工具以及后面要介绍的awk工具就能把替换的文本输出到屏幕上,而且还有其他更丰富的功能。sed和awk都是流式编辑器,是针对文档的行来操作的。

2.2.1打印某行

sed的格式为:sed -n 'n'p filename ,单引号内的n是一个数字,表示第几行。-n选项的作用是只显示我们要打印的行,无关紧要的内容不显示。示例命令如下:

[root@localhost ~]# sed -n '2'p /etc/passwd

bin:x:1:1:bin:/bin:/sbin/nologin

你可以去掉-n选项对比一下差异。要想把所有行都打印出来,可以使用命令sed -n '1,$'p filename,如下所示:

[root@localhost ~]# sed -n '1,$'p /etc/grep.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@localhost ~]# sed -n '1,3'p /etc/grep.txt

rot:x:0:0:/rot:/bin/bash

operator:x:11:0:operator:/root:/sbin/nologin

operator:x:11:0:operator:/rooot:/sbin/nologin

2.2.2打印包含某个字母的字符串的行

示例命令如下:

[root@localhost ~]# sed -n '/root/'p /etc/grep.txt

operator:x:11:0:operator:/root:/sbin/nologin

这种用法就类似于grep了,在grep中使用的特殊字符(如^,$,.,*等)同样也可以在sed中使用,如下所示:

[root@localhost ~]# sed -n '/^1/'p /etc/grep.txt

1111111111111111111111111111111

[root@localhost ~]# sed -n '/in$/'p /etc/grep.txt

operator:x:11:0:operator:/root:/sbin/nologin

operator:x:11:0:operator:/rooot:/sbin/nologin

[root@localhost ~]# sed -n '/r..o/'p /etc/grep.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@localhost ~]# sed -n '/ooo*/'p /etc/grep.txt

operator:x:11:0:operator:/root:/sbin/nologin

operator:x:11:0:operator:/rooot:/sbin/nologin

roooot:x:0:0:/rooooot:/bin/bash

sed命令加上-e选项可以实现多个行为,如下所示:

[root@localhost ~]# sed -e '1'p -e '/111/'p -n /etc/grep.txt

rot:x:0:0:/rot:/bin/bash

1111111111111111111111111111111

2.2.3删除某些行

示例命令如下:

[root@localhost ~]# sed '1'd /etc/grep.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

[root@localhost ~]# sed '1,3'd /etc/grep.txt

roooot:x:0:0:/rooooot:/bin/bash

1111111111111111111111111111111

Aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa

[root@localhost ~]# sed '/oot/'d /etc/grep.txt

rot:x:0:0:/rot:/bin/bash

1111111111111111111111111111111

aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa

这里参数d表示删除的动作,它不仅可以删除指定的单行以及多行,而且可以删除匹配某个字符的行,还可以删除从某一行开始到最后一行所有行。不过,这个操作仅仅是在显示器屏幕上并不显示这些行而已,文档还好好的。

2.2.4替换字符或者字符串

示例命令如下:

[root@localhost ~]# sed '1,2s/ot/to/g' /etc/grep.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

上例中的参数s就表示替换的动作,参数g表示本行全局替换,如果不加g则只替换本行出现的第一个,这个用法其实和vi的替换大同小异。

除了可以使用/作为分隔符外,我们还可以使用其他特殊字符,例如#和@。如下所示:

[root@localhost ~]# sed 's#ot#to#g' /etc/grep.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@localhost ~]# sed 's@ot@to@g' /etc/grep.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@localhost ~]# sed 's/[0-9]//g' /etc/grep.txt

rot:x:::/rot:/bin/bash

operator:x:::operator:/root:/sbin/nologin

operator:x:::operator:/rooot:/sbin/nologin

roooot:x:::/rooooot:/bin/bash

aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa

[0-9]表示任意的数字。这里你也可以提携程[a-zA-Z]或者[0-9a-zA-Z]。如下所示:

[root@localhost ~]# sed 's/[a-zA-Z]//g' /etc/grep.txt

::0:0:/://

::11:0::/://

::11:0::/://

::0:0:/://

1111111111111111111111111111111

2.2.5调换两个字符串的位置

示例命令如下:

[root@localhost ~]# sed 's/\(rot\)\(.*\)\(bash\)/\3\2\1/' /etc/grep.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

小括号在sed中属于特殊符号,必须在前面加转义字符\,替换时间则写成类似\1,\2或\3的形式。上例中用()把想要替换的字符打包成一个整体。有这个转义字符\,会让这个表达式看起来乱糟糟的,有个办法可以省略他。如下所示:

[root@localhost ~]# sed -r 's/(rot)(.*)(bash)/\3\2\1/' /etc/grep.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

没错正如你所看到的,就是这个-r选项让这个表达式更加清晰了。除了调换两个字符串的位置,还常常用sed在某一行前后增加指定内容,如下所示:

[root@localhost ~]# sed 's/^.*$/123&/' /etc/grep.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

2.2.6直接修改文件内容

示例命令如下:

[root@localhost ~]# sed -i 's/ot/to/g' /etc/grep.txt

[root@localhost ~]# cat /etc/grep.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

这样就可以直接更改grep.txt文件中的内容了。但需要注意,在修改前最好先备份文件,以免改错。

2.3awk工具的使用

awk也是流式编辑器,针对文档中的行来操作,一行一行的执行。awk兼具sed的所有功能,而且更加强大。

2.3.1截取文档中的某个段

示例命令如下:

[root@localhost ~]# head -2 /etc/grep.txt |awk -F ':' '{print $1}'

rto

operator

本例中,-F选项的作用是指定分隔符。如果不加-F选项,则以空格或者tab位分隔符。Print为打印的动作,用来打印某个字段。$1为第一个字段,$2为第二个字段,以此类推。但$0比较特殊,他表示整行:

[root@localhost ~]# head -2 /etc/grep.txt |awk -F':' '{print $0}'

rto:x:0:0:/rto:/bin/bash

operator:x:11:0:operator:/roto:/sbin/nologin

注意awk的格式,-F后面紧跟单引号,单引号里面为分隔符,print的动作要用{}括起来,否则会报错。配套还可以打印自定义内容,但是自定义的内容必须用括号括起来。如下所示:

[root@localhost ~]# head -2 /etc/grep.txt |awk -F ':' '{print $1"#"$2"#"$3}'

rto#x#0

operator#x#11

2.3.2匹配字符或者字符串

示例命令如下:

[root@localhost ~]# awk '/oo/' /etc/grep.txt

operator:x:11:0:operator:/rooto:/sbin/nologin

roooto:x:0:0:/rooooto:/bin/bash

这跟sed的用法类似,能实现grep的功能,但没有展示颜色,肯定没有grep用起来方便。不过awk还有比sed更强大的匹配,如下所示:

[root@localhost ~]# awk -F ':' '$1 ~/oo/' /etc/grep.txt

roooto:x:0:0:/rooooto:/bin/bash

他可以让某个段去匹配,这里~就是匹配的意思。awk还可以多次匹配,如下所示:

[root@localhost ~]# awk -F ':' '/root/ {print $1,$3} /test/ {print $1,$3}' /etc/grep.txt

operator 11

本例中awk匹配完root,在匹配test,他可以只打印所匹配的段。

2.3.3条件操作符

示例命令如下:

[root@localhost ~]# awk -F ':' '$3=="0"' /etc/passwd

root:x:0:0:root:/root:/bin/bash

Awk中可以用逻辑符号进行判断,比如==就是等于,也可以理解为精确匹配。另外还有>,>=,<,<=,!=等。值得注意的是,在和数字比较式,若把比较的数字用双引号引起来,那么awk不会认为是数字、会认为是字符,不加双引号则会认为是数字。

[root@localhost ~]# awk -F ':' '$3>=500' /etc/passwd

polkitd:x:999:998:User for polkitd:/:/sbin/nologin

chrony:x:998:996::/var/lib/chrony:/sbin/nologin

[root@localhost ~]# 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

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

!=表示不匹配,他除了针对某一个段的字符进行逻辑比较外,还可以在两个段之间进行逻辑比较。如下所示:

[root@localhost ~]# 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

[root@localhost ~]# 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

另外还可以使用&&和||,他们分别表示"并且"和"或者"。&&的用法如下:

[root@localhost ~]# awk -F ':' '$3>"5" && $3<"7"' /etc/passwd

shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown

||的用法如下:

[root@localhost ~]# awk -F ':' '$3>1000 || $7=="/bin/bash"' /etc/passwd

root:x:0:0:root:/root:/bin/bash

2.3.4awk的内置变量

awk常用的变量有OFS、NF和NR,OFS和-F选项有类似的功能,也是用来定义分隔符的,但是他在输出的时候定义,NF表示用分隔符的分隔后一共有多少段,NR表示行号。

OFS的用法示例如下:

[root@localhost ~]# 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@localhost ~]# awk -F ':' '{OFS="#"} {if ($3>100) {print $1,$2,$3,$4}}' /etc/passwd

systemd-network#x#192#192

polkitd#x#999#998

chrony#x#998#996

变量NF的具体用法如下:

[root@localhost ~]# head -n3 /etc/passwd | awk -F ':' '{print NF}'

7

7

7

[root@localhost ~]# head -n3 /etc/passwd | awk -F ':' '{print $NF}'

/bin/bash

/sbin/nologin

/sbin/nologin

这里NF是多少段,$NF是最后一段的值。NR的具体用法如下:

[root@localhost ~]# head -3 /etc/passwd | awk -F ':' '{print NR}'

1

2

3

我们还可以使用NR作为判断条件,如下所示:

[root@localhost ~]# awk 'NR>10' /etc/passwd

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

NR也可以配合段匹配一起是使用,如下所示:

[root@localhost ~]# awk -F ':' 'NR<20 && $1 ~ /root/' /etc/passwd

root:x:0:0:root:/root:/bin/bash

2.3.5awk中的数学运算

awk可以更改段值,示例命令如下:

[root@localhost ~]# 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

awk也可以对各个段的值进行数学运算,示例命令如下:

[root@localhost ~]# head -n2 /etc/passwd

root:x:0:0:root:/root:/bin/bash

bin:x:1:1:bin:/bin:/sbin/nologin

[root@localhost ~]# 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

awk还可以计算某个段的总和,示例命令如下:

[root@localhost ~]# awk -F ':' '{(tot=tot+$3)}; END {print tot}' /etc/passwd

2605

这里的END是awk特有的语法,表示所有的行都已经执行。其实awk连同sed都可以写成一个脚本文件,而且有他们特有的语法。在awk中使用if判断、for循环都可以,如下所示:

[root@localhost ~]# awk -F ':' '{if ($1=="root") {print $0}}' /etc/passwd

root:x:0:0:root:/root:/bin/bash

相关推荐
wangjun515911 小时前
java 转义 反斜杠 Unexpected internal error near index 1
java·正则表达式·反斜杠
刘某的Cloud12 小时前
shell-条件判断
linux·运维·服务器·shell
背太阳的牧羊人13 小时前
df.replace({‘b‘: r‘\s*\.\s*‘}, {‘b‘: np.nan}, regex=True)
python·正则表达式
勇敢磊磊学IT14 小时前
IO编程与正则表达式
python·正则表达式
君败红颜15 小时前
Java 正则表达式入门与应用(详细版)
java·python·正则表达式
bin91531 天前
正则表达式{}和(),pyhton里的正则表达式,函数findall解析
python·正则表达式·findall
whisperrr.2 天前
掌握正则表达式:从入门到精通的实战指南
正则表达式·软件工程
问道飞鱼3 天前
【Linux知识】shell编程知识科普
linux·运维·chrome·shell
NSJim3 天前
Linux系统自动化sh脚本
linux·shell·自动化脚本