正则三剑客

正则元字符

  • ^:两种用法:

    1. ^[0-9]:表示匹配以数字(也可以是字符或其他)开头的行;

    2. [^0-9]:表示匹配非数字(也可以是字符或其他)的字符;

  • $:以什么结尾

  • .:用于匹配除了换行符以外的任意一个字符。

  • *:表示前面的字符可以出现0次或多次。

  • ?:表示前面的字符可以出现0次或1次。

  • +:表示前面的字符可以出现1次或多次。

  • {n}:表示前面的字符必须恰好出现n次。

  • {n,}:表示前面的字符至少出现n次。

  • {n,m}:表示前面的字符至少出现n次,但不超过m次。

  • []:匹配集合中的,如:

    • [lL]ove:匹配love并忽略l的大小写;

  • [x-y]:匹配集合范围内的,如:

    • [0-9]:匹配所有数字;

    • [a-z]:所有小写字母;

  • \:转义。将特殊含义的符号转义成普通符号。如:

    • 'love\.':转义后的.不会再匹配单个字符。

  • \d:表示匹配一个数字,等同于[0-9]

  • \D:表示匹配一个非数字字符,等同于[^0-9]

  • \w:表示匹配包括下划线的任何单词字符,等同于[A-Za-z0-9_]

  • \W:表示匹配任何非单词字符,等同于[^A-Za-z0-9_]


  • \<:以什么开头;'\<love'匹配以love开头的所有行。

  • \>:以什么结尾;'love\>'匹配以love结尾的所有行。

grep

语法及选项

grep [选项] 查找条件 [目标文件]

    -c:打印符合要求一共有多少行数;
    -i:忽略大小写;
    -n:输出符合要求的行及其行号;
    -v:取反;
    -r:遍历所有的子目录;
    -A:后面跟一个数字,如-A2表示打印符合要求的行及下面的两行;
    -B:后面跟一个数字,如-B2表示打印符合要求的行及上面的两行;
    -C:后面跟一个数字,如-C2表示打印符合要求的行及上下各两行;
    -E:使其支持扩展正则,等同于egrep。

扩展正则:
指的是表达式中含有:+>|(){}等符号,在grep中需要用转义符\脱义,如下3个命令等同:

grep '^ab\?c' 1.txt
egrep '^ab?c' 1.txt
grep -E '^ab?c' 1.txt

grep选项示例

过滤passwd文件中的nologin字符

$ grep 'nologin' passwd

-c 查看符合要求共有多少行

$ grep -c 'nologin' passwd

-n 显示筛选条件所在行号

$ grep -n 'nologin' passwd

-i 筛选忽略大小写

$ grep -i 'nologin' passwd

-v 取反,打印不包含nologin以外的行

$ grep -v 'nologin' passwd

-A2 筛选包含root的行及下面两行

[root@lwz1 grep]# grep -A2 'root' passwd
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/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

grep正则示例

筛选字母l开头的行,并忽略大小写,显示行号

[root@lwz1 grep]# grep -n '^[lL]' passwd
5:lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
23:lwz:x:1000:1000:lwz:/home/lwz:/bin/bash
24:LWZ:x:1001:1001::/home/LWZ:/bin/bash

筛选除大写字母L开头以外的行

$ grep -v '^[L]' passwd

筛选r与o之间包含任意一个字符的行

[root@lwz1 grep]# grep 'r.o' passwd
root:x:0:0:root:/root:/bin/bash
operator:x:11:0:operator:/root:/sbin/nologin
rao

.:任意一个字符
+:任意一个或多个字符
?:0个或一个字符

筛选连续出现2次o的行

[root@lwz1 grep]# grep -E 'o{2}' 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

注意:{}中的数字表示重复的次数;
{2,}:连续出现至少2次以上;
{,2}:连续出现最多2次以内;
{2,5}:连续出现2次到5次之间;

同时筛选多个参数

[root@lwz1 grep]# grep -E 'root|nologin|lwz' passwd
root:x:0:0:root:/root:/bin/bash
mail:x:8:12:mail:/var/spool/mail:/sbin/nologin
operator:x:11:0:operator:/root:/sbin/nologin
lwz:x:1000:1000:lwz:/home/lwz:/bin/bash

sed

sed是一种流编辑器,它一次处理一行内容。处理时,把当前处理的行存储在临时缓冲区中,称为“模式空间”,接着用sed命令处理缓冲区中的内容,处理完成后,把缓冲区的内容送往屏幕。接着处理下一行,这样不断重复,直到文件末尾。文件内容并没有改变,除非你使用重定向存储输出。

语法

sed [选项] '{命令参数}[flags]' 文件名

    选项:
        -e script     在命令行执行多个编辑器命令。
        -f namefile   调用包含sed命令的文件来执行,批量执行是可用这种方式。
        -n            抑制自动输出。
        -i            编辑文件内容,可以用来删除源文件中的内容。
        -i.bak        编辑文件同时创建.bak备份文件。
        -r            使用扩展的正则表达式。
        !             取反(gen在模式条件后与shell有所区别)

    命令参数:
        a   在匹配参数后面添加
        i   在匹配参数前面添加
        p   打印
        d   删除
        s   查找替换
        c   更改
        y   转换    N D P

    flags:
        数字        处理匹配到的每行中第几个结果。
        g           匹配到的所有结果。
        p           打印原始内容。
        w filename  将处理后的结果写入指定的filename。

命令参数示例

示例文本:

1 the quick brown fox jumps over the lazy dog.
2 the quick brown fox jumps over the lazy dog.
3 the quick brown fox jumps over the lazy dog.
4 the quick brown fox jumps over the lazy dog.
5 the quick brown fox jumps over the lazy dog.

a 指定范围内的行下面增加内容

[root@lwz1 sed]# sed '2,4a\append data 'haha'' sed.txt
1 the quick brown fox jumps over the lazy dog.
2 the quick brown fox jumps over the lazy dog.
append data haha
3 the quick brown fox jumps over the lazy dog.
append data haha
4 the quick brown fox jumps over the lazy dog.
append data haha
5 the quick brown fox jumps over the lazy dog.

说明:a表示在匹配的行下面新增内容。2,4a表示2到4行,如果不写数字,表示匹配所有行。\转义符可以不写,写上方便查看。

# 匹配包含指定字符串的行下面新增内容
[root@lwz1 sed]# sed '/3 the/a\append data ' sed.txt
1 the quick brown fox jumps over the lazy dog.
2 the quick brown fox jumps over the lazy dog.
3 the quick brown fox jumps over the lazy dog.
append data
4 the quick brown fox jumps over the lazy dog.
5 the quick brown fox jumps over the lazy dog.

说明:sed '/要匹配的字符串/a\要新增的内容' 文件名

i 匹配包含指定字符串的行上面新增内容

[root@lwz1 sed]# sed '/5 the/i\append data' sed.txt
1 the quick brown fox jumps over the lazy dog.
2 the quick brown fox jumps over the lazy dog.
3 the quick brown fox jumps over the lazy dog.
4 the quick brown fox jumps over the lazy dog.
append data
5 the quick brown fox jumps over the lazy dog.

s 替换指定范围行中的指定字符串

[root@lwz1 sed]# sed '2,4s/dog/cat/' sed.txt
1 the quick brown fox jumps over the lazy dog.
2 the quick brown fox jumps over the lazy cat.
3 the quick brown fox jumps over the lazy cat.
4 the quick brown fox jumps over the lazy cat.
5 the quick brown fox jumps over the lazy dog.

sed '指定范围s/被替换/替换后/' 文件名
如果指定字符串为定义行:sed '/3 the/s/dog/cat/' 文件名

c 替换匹配到的行内容

[root@lwz1 sed]# sed '2,4cchange data haha' sed.txt
1 the quick brown fox jumps over the lazy dog.
change data haha
5 the quick brown fox jumps over the lazy dog.
[root@lwz1 sed]# sed '2,4c\change data haha' sed.txt    # 两种写法都可。

y 字符转换,将内容中的a b c转换为大写

[root@lwz1 sed]# sed 'y/abc/ABC/' sed.txt
1 the quiCk Brown fox jumps over the lAzy dog.
2 the quiCk Brown fox jumps over the lAzy dog.

说明:也可以转换为其他的任意单个字符

d 删除整行

[root@lwz1 sed]# sed '1,4d' sed.txt
5 the quick brown fox jumps over the lazy dog.

p 打印输出

[root@lwz1 sed]# sed '/2 the/p' sed.txt
1 the quick brown fox jumps over the lazy dog.
2 the quick brown fox jumps over the lazy dog.
2 the quick brown fox jumps over the lazy dog.
3 the quick brown fox jumps over the lazy dog.

说明:sed默认会打印。原因是打印了指定文件内容一次,又将读入缓存的所有数据打印了一次,所以会看到这样的效果,加上选项-n可以避免。

打印指定字符串开头的行

[root@lwz1 sed]# sed '/2 the/p' sed.txt -n
2 the quick brown fox jumps over the lazy dog.

指定打印12和13行的内容

sed -n '12,13p' sed.txt

选项示例

-e 同时执行多个命令

[root@lwz1 sed]# sed -e 's/brown/green/' -e 's/dog/cat/' sed.txt

[root@lwz1 sed]# sed -e 's/brown/green/;s/dog/cat/' sed.txt     # 两条命令效果相同。
1 the quick green fox jumps over the lazy cat.
2 the quick green fox jumps over the lazy cat.

-f 从文件读取编辑器命令

适用于日常重复执行的场景

[root@lwz1 sed]# vi abc.txt    # 创建一个包含sed命令的文件
1s/brown/green/
2y/abc/ABC/
3c\linyi
4a\123

[root@lwz1 sed]# sed -f abc.txt sed.txt     # 使用-f选项调用
1 the quick green fox jumps over the lazy dog.
2 the quiCk Brown fox jumps over the lAzy dog.
linyi
4 the quick brown fox jumps over the lazy dog.
123
5 the quick brown fox jumps over the lazy dog.

-i.bak 修改文件内容,并将源文件备份成.bak

[root@lwz1 sed]# sed -i.bak 's/dog/cat/' sed.txt        # 加上-i.bak选项

[root@lwz1 sed]# cat sed.txt        # 替换后的文件
1 the quick brown fox jumps over the lazy cat.

[root@lwz1 sed]# cat sed.txt.bak        # 备份的源文件
1 the quick brown fox jumps over the lazy dog.

-r 正则示例

/key/查询匹配关键字的行

[root@lwz1 sed]# sed -n '/cat/p' sed.txt

/key1/,/key2/匹配两个关键字之间的行

[root@lwz1 sed]# sed -n '/^3/,/^cat/p' sed.txt

/key/,x从匹配关键字的行开始到文件第x行之间的行(包含关键字所在行)

[root@lwz1 sed]# sed -n '/^3 the/,7p' sed.txt

x,/key/从文件的第x行开始到与关键字的匹配之间的行

[root@lwz1 sed]# sed -n '3,/cat$/p' sed.txt

x,y!不包含x到y的行

[root@lwz1 sed]# sed -n '3,4!p' sed.txt
1 the quick brown fox jumps over the lazy cat.
2 the quick brown fox jumps over the lazy cat.
5 the quick brown fox jumps over the lazy cat.

/key/!不包含关键字的行

[root@lwz1 sed]# sed -n '/cat$/!p' sed.txt      # 不以cat结尾的行

flags示例

示例文件

[root@lwz1 sed]# vi flags.txt
1 the quick brown fox jumps over the lazy dog . dog
2 the quick brown fox jumps over the lazy dog . dog
3 the quick brown fox jumps over the lazy dog . dog

d 删除范围内的行

[root@lwz1 sed]# sed -i '4,5d' flags.txt        # 删除源文件4行到5行

数字2 替换每行中第二次匹配到的关键字

[root@lwz1 sed]# sed 's/dog/cat/2' flags.txt
1 the quick brown fox jumps over the lazy dog . cat
2 the quick brown fox jumps over the lazy dog . cat

说明:s参数默认只替换每行中第一次匹配到的关键字

g 匹配行中所有关键字

[root@lwz1 sed]# sed '/3 the/s/dog/cat/g' flags.txt
1 the quick brown fox jumps over the lazy dog . dog
2 the quick brown fox jumps over the lazy dog . dog
3 the quick brown fox jumps over the lazy cat . cat

w 将修改后的内容存入指定文件中

[root@lwz1 sed]# sed '3s/dog/cat/w w.txt' flags.txt
1 the quick brown fox jumps over the lazy dog . dog
2 the quick brown fox jumps over the lazy dog . dog
3 the quick brown fox jumps over the lazy cat . dog

[root@lwz1 sed]# cat w.txt
3 the quick brown fox jumps over the lazy cat . dog

sed小技巧

统计文件有多少行

# 一共多少行
[root@lwz1 sed]# sed -n '$=' /etc/passwd     
24

# 显示行号并输出内容
[root@lwz1 sed]# sed '=' /etc/passwd        

# 查看关键字行号
[root@lwz1 sed]# sed '/lwz/=' /etc/passwd -n    

以某某结尾或者开头的行

# 数字开头的行
[root@lwz1 sed]# sed '/^[0-9]/p' sed.txt -n
1 the quick brown fox jumps over the lazy cat.

# c或者h结尾的行
[root@lwz1 sed]# sed '/[c,h]$/p' /etc/passwd -n
root:x:0:0:root:/root:/bin/bash
sync:x:5:0:sync:/sbin:/bin/sync
lwz:x:1000:1000:lwz:/home/lwz:/bin/bash
LWZ:x:1001:1001::/home/LWZ:/bin/bash

开头或末尾添加或删除

# 文件中2到4行开头添加#,可以用于脚本注释
[root@lwz1 sed]# sed '2,4s/^/#/' sed.txt
1 the quick brown fox jumps over the lazy cat.
#2 the quick brown fox jumps over the lazy cat.
#3 the quick brown fox jumps over the lazy cat.
#4 the quick brown fox jumps over the lazy cat.
5 the quick brown fox jumps over the lazy cat.

# 将文件中不以#开头的行的行首添加#
[root@lwz1 sed]# sed 's/^[^#]/#&/' sed.txt

# 删除文件中所有以#开头,后面至少跟一个空白字符的行的行首的#和空白字符
[root@lwz1 sed]# sed 's/^#[[:space:]]*//' sed.txt

# 匹配2,5行中以#开头的行,并将#替换为空,类似删除
[root@lwz1 sed]# sed '2,5s/^#//' sed.txt        # 如果不定义以#开头的话,第5行中的#也会被删除。
1 the quick brown fox jumps over the lazy cat.
2 the quick brown fox jumps over the lazy cat.
3 the quick brown fox jumps over the lazy cat.
4 the quick brown fox jumps over the lazy cat.
5# the quick brown fox jumps over the lazy cat.

# 匹配包含cat关键词的所有行,并将结尾的#替换为空,类似删除
[root@lwz1 sed]# sed '/cat/s/#$//' sed.txt

awk

语法

awk [选项] 'BEGIN{commands} pattern{commands} END{commands}' filename

    选项:
        -F:指定内容中的分隔符(默认空格)
        -v:赋值用户自定义的变量
        -f:指定脚本文件,从脚本中读取awk命令

    BEGIN{commands}:开始块,awk数据处理前执行的命令(可选),在语句中只执行一次。BEGIN必须大写。可用作:
        1.设置变量计数起始值。
        2.打印头部信息。
        3.改变字段的分隔符。
        4.打开文件。

    END{commands}:结束块。awk数据处理后执行的命令(可选),在语句中只执行一次。END必须大写。语句:
        1.输出统计的结果。
        2.打印结尾信息。
        3.关闭文件。

    pattern{commands}:对文件的每一行遍历,判断是否满足pattern的模式,如果满足则执行脚本。
        内置变量:
            $n:列的内容。例如:$1表示第一列、$2表示第二列。
            $0:行的内容。
            FILENAME:当前输入的文件名。
            FS:指定字段分隔符(默认是空格)
            NF:字段数,在执行过程中对应于当前的字段数,NF:列的个数。
            NR:显示行号,或者指定某行。
            FNR:各文件分别计数的行号。
            OFS:指定内容输出时字段的分隔符(默认空格)
            ORS:指定内容输出时行的分隔符(默认换行符)
            RS:行分隔符(默认换行符)
            ~:匹配
            !~:不匹配
            \n:换行符

        正则表达式:
            /root/:匹配包含root的行。

        关系表达式:
            <:小于;<=:小于等于。
            >:大于;>=:大于等于。
            &&:逻辑与,两个条件同时成立,则为真。
            ||:逻辑或。两个条件中成立一项,则为真。
            +:数值相加。
            *:数值相乘。

        匹配表达式:
            ~:匹配。
            !~:不匹配。
            ==:等于,精确匹配。
            !=:不等于。

awk的工作流程:

  1. 读:从文件、管道或者标准输入中读入一行然后把它存放到内存中。

  2. 执行:根据awk命令按顺序执行读取到的行数据。

  3. 重复:一直重复上述两个过程直到文件结束。

示例

-F 指定分隔符,并打印第一段

[root@lwz1 sed]# awk -F: '{print $1}' passwd.txt

打印所有行内容

[root@lwz1 sed]# awk '{print $0}' passwd.txt

匹配字符或者字符串

打印包含oo的所有行。

[root@lwz1 sed]# awk '/oo/ {print $0}' passwd.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

第一段中包含oo的行

[root@lwz1 sed]# awk -F: '$1~/oo/' passwd.txt
root:x:0:0:root:/root:/bin/bash

或者
[root@lwz1 sed]# awk -F: '$1~/oo/ {print $0}' passwd.txt

多个匹配条件

[root@lwz1 sed]# awk -F: '/root/ {print $1,$3} /bash/ {print $1,$3,$7}' passwd.txt
root 0
root 0 /bin/bash
operator 11
lwz 1000 /bin/bash
LWZ 1001 /bin/bash

说明:-F指定分隔符为:,打印文本中包含root的行的第一段和第三段,包含bash的行的第一、三、七段。

条件匹配与判断

精确匹配第三段中等于0的行

[root@lwz1 sed]# awk -F: '$3==0' passwd.txt
root:x:0:0:root:/root:/bin/bash

判断第三段中大于等于500的行

[root@lwz1 sed]# awk -F: '$3>=500' passwd.txt
nobody:x:65534:65534:Kernel Overflow User:/:/sbin/nologin
systemd-coredump:x:999:997:systemd Core Dumper:/:/sbin/nologin
polkitd:x:998:996:User for polkitd:/:/sbin/nologin

判断第三段小于第四段的行

[root@lwz1 sed]# awk -F: '$3<$4' passwd.txt
adm:x:3:4:adm:/var/adm:/sbin/nologin
lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin

||逻辑或的用法

[root@lwz1 sed]# awk -F: '$3>100 || $7=="/sbin/nologin"' passwd.txt
bin:x:1:1:bin:/bin:/sbin/nologin        # 第七段等于/sbin/nologin成立。
daemon:x:2:2:daemon:/sbin:/sbin/nologin
lwz:x:1000:1000:lwz:/home/lwz:/bin/bash         # 第三段大于100成立。

&&逻辑与的用法

[root@lwz1 sed]# awk -F: '$1=="lwz" && $3 ~ 0' passwd.txt
lwz:x:1000:1000:lwz:/home/lwz:/bin/bash

说明:第一段为lwz,并且第三段包含0的行同时达成,则匹配。

内置变量用法

OFS指定分隔符用法:
[root@lwz1 sed]# awk -F: '{OFS="#"} $3>1000 || $7~/bash/ {print $1,$3,$7}' passwd.txt
root#0#/bin/bash
nobody#65534#/sbin/nologin

# 或者使用如下方法
[root@lwz1 sed]# awk -F: '$3>1000 || $7~/bash/ {print $1"~"$3"~"$7}' passwd.txt
root~0~/bin/bash
nobody~65534~/sbin/nologin

说明:OFS指定分隔符为#,在匹配||两边的条件,符合一项则成立。

NR表示行,用法:
# 用NR显示行号
[root@lwz1 sed]# awk '{print NR":"$0}' passwd.txt

# NR匹配前3行,打印并显示行号
[root@lwz1 sed]# awk -F: 'NR<=3 {print NR,$0}' passwd.txt
1 root:x:0:0:root:/root:/bin/bash
2 bin:x:1:1:bin:/bin:/sbin/nologin
3 daemon:x:2:2:daemon:/sbin:/sbin/nologin

# 匹配前3行中包含root和daemon的行
[root@lwz1 sed]# awk -F: 'NR<=3 && $0~/root|daemon/' passwd.txt
root:x:0:0:root:/root:/bin/bash
daemon:x:2:2:daemon:/sbin:/sbin/nologin
NF表示段,用法:
# 显示每一行有多少段
[root@lwz1 sed]# awk -F: '{print NF":"$0}' passwd.txt
7:root:x:0:0:root:/root:/bin/bash

数学运算符用法

更改某一段的值:

[root@lwz1 sed]# head -n 3 passwd.txt | 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的共有哪些行:

[root@lwz1 sed]# awk -F: '$1=="root"' passwd.txt
root:x:0:0:root:/root:/bin/bash

计算某一段的总和:

[root@lwz1 sed]# awk -F: '{tot=tot+$3} END {print tot}' passwd.txt
73000

说明:tot在awk中表示累加器,用来存储和累加某个变量的值,累加器默认从0开始;tot=tot+$3表示将$3的值累加到tot中。这里使用END表示只输出最后tot的值。