shell编程之正则表达式

正则表达式(regular expression, RE)是一种字符模式,用于在查找过程中匹配指定的字符。在大多数程序里,正则表达式都被置于两个正斜杠之间;例如/l[oO]ve/就是由正斜杠界定的正则表达式,它将匹配被查找的行中任何位置出现的相同模式。在正则表达式中,元字符是最重要的概念。

工具:被vim、sed、awk、grep调用

场景:mysql、oracle、php、python ,Apache,Nginx...  需要正则

一、元字符

元字符是这样一类字符,它们表达的是不同于字面本身的含义

1、基本正则表达式元字符

^  行首定位符 

[root@localhost ~]# grep "root" /etc/passwd
root:x:0:0:root:/root:/bin/bash
operator:x:11:0:operator:/root:/sbin/nologin


[root@localhost ~]# grep "^root" /etc/passwd  //以root开头的
root:x:0:0:root:/root:/bin/bash

  $  行尾定位符

[root@master1 ~]# grep "love$" 1.txt  //以love为结尾的
love
ilove

.  匹配单个任意字符

[root@localhost ~]# grep abc 1.txt
abc
[root@localhost ~]# grep adc 1.txt
adc
[root@localhost ~]# grep a.c 1.txt
abc
adc

*  匹配前导符0到多次

[root@localhost ~]# cat 1.txt 
a
ab
abc
abcd
abcde
abcdef
ggg
hhh
iii
[root@localhost ~]# grep "abc*" 1.txt 
ab
abc
abcd
abcde
abcdef
[root@localhost ~]# grep "abcd*" 1.txt 
abc
abcd
abcde
abcdef

.*  任意多个字符

[root@localhost ~]# grep ".*" 1.txt 
a
ab
abc
abcd
abcde
abcdef
ggg
hhh
iii

[]  匹配指定范围内的一个字符

[lL]ove   //Love和love都可以输出出来

[-]  匹配指定范围内的一个字符,连续的范围

[a-z0-9]ove       

[^]  匹配不在指定组内的字符   (取反)

[root@localhost~]# cat  1.txt
love
1ove
|ove

[root@localhost~]# grep [0-9a-Z]ove  1.txt
love
1ove
[root@localhost ~]# grep [^0-9a-Z]ove 1.txt
|ove

\  用来转义元字符      (''   ""    \),脱意符


[root@localhost ~]# grep "l." 1.txt 
love
l.ve
[root@localhost ~]# grep "l\." 1.txt 
l.ve

\<  词首定位符   //以什么为词的开头

[root@localhost ~]# grep "love" 1.txt 
love
iloveyou
[root@localhost ~]# grep "\

\>  词尾定义符

love\>    //以love为词的结尾

()  稍后使用字符的标签

 ps:()为了后面的调用。  \1调用前面()里的内容。

:% s/172.16.130.1/172.16.130.5/
:% s/\(172.16.130.\)1/\15/
:% s/\(172.\)\(16.\)\(130.\)1/\1\2\35/
:3,9 s/\(.*\)/#\1/	加注释

x\{m\}  字符x重复出现m次

[root@localhost ~]# grep o 1.txt
love
loove
looove
[root@localhost ~]# grep "o\{3\}" 1.txt
looove

x\{m,\}  字符x重复m次以上

x\{m,n}  字符出现m到n次

[root@localhost ~]# egrep "o{4,5}" 1.txt 
oooo
ooooo
ioooo
ooooi
iooooi
[root@localhost ~]# egrep "o{5,5}" 1.txt 
ooooo

2、扩展正则表达式元字符

+  匹配1-n个前导字符

[root@localhost ~]# cat 1.txt
lve
love
loove
[root@localhost ~]# egrep lo+ve 1.txt
love
loove

? 匹配0-n个前导字符

ps:lo?ve :?前面的o 有还是没有,都行!

[root@localhost ~]# egrep lo?ve tom.sh 
love
lve

a|b  匹配a或b

[root@localhost ~]# egrep "o|v" 1.txt 
lve
1ove
loove
looove
loeve
love
Love
iloveyou
l.ve
o
oo
ooo
oooo
ooooo
ioooo
ooooi
iooooi

() 组字符

[root@localhost ~]# egrep "loveable|rs" 1.txt 
rs
loveable
lovers
[root@localhost ~]# egrep "love(able|rs)" 1.txt 
loveable
lovers

二、grep

1、目的:过滤,查找文档中的内容

2、分类

① grep

② egrep:扩展支持正则

\w 所有字母与数字,称为字符[a-zA-Z0-9]        'l[a-zA-Z0-9]*ve'         ===       'l\w*ve'

\W 所有字母与数字之外的字符,称为非字符     'love[^a-zA-Z0-9]+'     ===    'love\W+'

\b 词边界                                                             '\'               ===             '\blove\b

③ fgrep:就不支持正则

[root@localhost ~]# fgrep . 1.txt
l.ve

3、返回值

0 就是找到了,表示成功。

1 是没有,表示在所提供的文件无法找到匹配的pattern(模板)。

 2 找到的地不对。

 ## grep 'root' /etc/passwd
    root:x:0:0:root:/root:/bin/bash
    operator:x:11:0:operator:/root:/sbin/nologin
 ## echo $?
    0
    
 ## grep 'root1' /etc/passwd  #用户root1并不存在
 ## echo $?
    1
    
 ## grep 'root' /etc/passwd1  #这里的/etc/passwd1文件并不存在
    grep: /etc/passwd1: No such file or directory
 ## echo $?
    2

 4、参数

grep -q  静默  (输出的结果不在屏幕上显示)

[root@localhost ~]# grep "5\.." 1.txt
5.1
5.2
5.a
5.b
5..
5...
5.aaa
[root@localhost ~]# grep -q "5\.." 1.txt
[root@localhost ~]# echo $?
0

grep -v 取反

grep -R  可以查目录下面的文件

[root@localhost ~]# grep  xulei  /home/
grep: /home/: 是一个目录
[root@localhost ~]# grep -R  xulei  /home/
/home/xulei/.cache/gdm/session.log
/home/xulei/.cache/imsettings/log   [HOME=/home/xulei/.config/imsettings]
匹配到二进制文件 /home/xulei/.cache/tracker/meta.db
匹配到二进制文件 /home/xulei/.cache/tracker/meta.db-wal

grep -o  只找到这个关键词就可以

[root@localhost ~]# grep "a" 1.txt
5.a
5.aaa
a
ab
abc
abcd
abcde
abcdef
loveable
ldfadasfsdave
[root@localhost ~]# grep -o  "a" 1.txt
a
a
a
a
a
a
a
a
a
a
a
a
a
a

grep -B2  前两行

grep -A2 后两行

grep -C2 上下两行

egrep -l 只要文件名

[root@localhost ~]# egrep -l 'root' /etc/passwd
/etc/passwd

egrep -n 带行号

[root@localhost ~]# egrep -n 'xulei' /etc/passwd
43:xulei:x:1000:1000::/home/xulei:/bin/bash

示例:

grep -E 或egrep使用

egrep 'NW' datafile  :在datafile文件中,找NW

egrep 'NW' d*:找NW,文件只要是d开头的就可以

egrep '^n' datafile:以n开头的行

egrep '4$' datafile:以4结尾的行

egrep TB Savage datafile:找TB,在savage里找,在datafile里找

egrep 'TB Savage' datafile:找TB Savage

egrep '5\..' datafile:找5点后面是任意一个字符

egrep '\.5' datafile:找点五

egrep '^[we]' datafile:找w或e开头的

egrep '[^0-9]' datafile:找不是0-9的

egrep '[A-Z][A-Z] [A-Z]':找两个大写,一个空格,在有一个大写的行

egrep 'ss*' datafile:找s开头,0到多个s

egrep '[a-z]{9}' datafile:找小写字母出现9次的

egrep '\

egrep '\' datafile:就找这个词

egrep '\<[a-r].*n\>' datafile:a或r开头,中间任意,n结尾

三、sed

前言:

Stream EDitor:流编辑

sed 是一种在线的、非交互式的编辑器,它一次处理一行内容。处理时,把当前处理的行存储在临时缓冲区中,称为“模式空间”(pattern space),接着用sed命令处理缓冲区中的内容,处理完成后,把缓冲区的内容送往屏幕。接着处理下一行,这样不断重复,直到文件末尾。文件内容并没有改变,除非你使用重定向存储输出。Sed主要用来自动编辑一个或多个文件;简化对文件的反复操作;

文本文件->“模式空间”(pattern space)->屏幕
逐行处理
内容未变

格式:

1、sed   选项  命令 文件 
    sed [options] 'command' file(s)
2、sed     选项 –f 脚本 文件
    sed [options] -f scriptfile file(s) 

返回值:

都是0,不管对错。只有当命令存在语法错误时,sed的退出状态才是非0。

sed和正则表达式:与grep一样,sed在文件中查找模式时也可以使用正则表达式(RE)和各种元字符。正则表达式是括在斜杠间的模式,用于查找和替换,以下是sed支持的元字符。

使用基本元字符集    ^, $, ., *, [], [^], \< \>,\(\),\{\}
使用扩展元字符集    ?, +, |, ( )

使用扩展元字符的方式:

   \+           转义
    sed -r      加-r

汇总示例

编辑文件删除命令  d:

[root@master1 ~]# sed -r '/root/d' passwd //匹配词组删除,删除有root的行
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
[root@master1 ~]# sed -r '3d' passwd  //删除第三行
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/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@master1 ~]# sed -r '3{d}' passwd
root:x:0:0:root:/root:/bin/bash 1
bin:x:1:1:bin:/bin:/sbin/nologin 2
adm:x:3:4:adm:/var/adm:/sbin/nologin 4
lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin 5
sync:x:5:0:sync:/sbin:/bin/sync 6
shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown 7
halt:x:7:0:halt:/sbin:/sbin/halt 8
mail:x:8:12:mail:/var/spool/mail:/sbin/nologin 9
operator:x:11:0:operator:/root:/sbin/nologin 10

{存放sed的多个命令} 例如:3{h;d},h暂存空间

[root@master1 ~]# sed -r '3{d;}' passwd
root:x:0:0:root:/root:/bin/bash 1
bin:x:1:1:bin:/bin:/sbin/nologin 2
adm:x:3:4:adm:/var/adm:/sbin/nologin 4
lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin 5
sync:x:5:0:sync:/sbin:/bin/sync 6
shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown 7
halt:x:7:0:halt:/sbin:/sbin/halt 8
mail:x:8:12:mail:/var/spool/mail:/sbin/nologin 9
operator:x:11:0:operator:/root:/sbin/nologin 10

删除3行到最后一行'3,$d'

[root@master1 ~]# sed -r '3,$d' passwd
root:x:0:0:root:/root:/bin/bash 1
bin:x:1:1:bin:/bin:/sbin/nologin 2

删除最后一行: 

[root@master1 ~]# sed -r '$d' passwd
root:x:0:0:root:/root:/bin/bash 1
bin:x:1:1:bin:/bin:/sbin/nologin 2
daemon:x:2:2:daemon:/sbin:/sbin/nologin 3
adm:x:3:4:adm:/var/adm:/sbin/nologin 4
lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin 5
sync:x:5:0:sync:/sbin:/bin/sync 6
shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown 7
halt:x:7:0:halt:/sbin:/sbin/halt 8
mail:x:8:12:mail:/var/spool/mail:/sbin/nologin 9

替换命令 s:

[root@master1 ~]# sed -r 's/root/aofa/' passwd
aofa:x:0:0:root:/root:/bin/bash 1
bin:x:1:1:bin:/bin:/sbin/nologin 2
daemon:x:2:2:daemon:/sbin:/sbin/nologin 3
adm:x:3:4:adm:/var/adm:/sbin/nologin 4
lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin 5
sync:x:5:0:sync:/sbin:/bin/sync 6
shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown 7
halt:x:7:0:halt:/sbin:/sbin/halt 8
mail:x:8:12:mail:/var/spool/mail:/sbin/nologin 9
operator:x:11:0:operator:/aofa:/sbin/nologin 10

全局替换

[root@master1 ~]# sed -r 's/root/aofa/g' passwd  //全部的root被替换掉了  g:全局替换
aofa:x:0:0:aofa:/aofa:/bin/bash 1
bin:x:1:1:bin:/bin:/sbin/nologin 2
daemon:x:2:2:daemon:/sbin:/sbin/nologin 3
adm:x:3:4:adm:/var/adm:/sbin/nologin 4
lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin 5
sync:x:5:0:sync:/sbin:/bin/sync 6
shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown 7
halt:x:7:0:halt:/sbin:/sbin/halt 8
mail:x:8:12:mail:/var/spool/mail:/sbin/nologin 9
operator:x:11:0:operator:/aofa:/sbin/nologin 10

查找双数   结尾的词组
&:替换成    双数.5
&有查询结果的含义。 

# sed -r 's/[0-9][0-9]$/&.5/' passwd 
[root@localhost ~]# sed -r 's/[0-9][0-9]$/&.5/' passwd 
root:x:0:0:root:/root:/bin/bash1
bin:x:1:1:bin:/bin:/sbin/nologin2
daemon:x:2:2:daemon:/sbin:/sbin/nologin3
adm:x:3:4:adm:/var/adm:/sbin/nologin4
lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin5
sync:x:5:0:sync:/sbin:/bin/sync6
shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown7
halt:x:7:0:halt:/sbin:/sbin/halt8
mail:x:8:12:mail:/var/spool/mail:/sbin/nologin9
operator:x:11:0:operator:/root:/sbin/nologin10.5

 sed -r 's/(mail)/E\1/g' passwd
    ()括号组合字符,\1调用括号

[root@localhost ~]# sed -r 's/(mail)/E\1/g' passwd 
Email:x:8:12:Email:/var/spool/Email:/sbin/nologin9

sed -r 's#(mail)#E\1#g' passwd
    分隔符可以换成#号

读文件命令r:

//最后一行,读取新文件1.txt
[root@localhost ~]# sed -r '$r 1.txt' passwd 
root:x:0:0:root:/root:/bin/bash1
bin:x:1:1:bin:/bin:/sbin/nologin2
daemon:x:2:2:daemon:/sbin:/sbin/nologin3
adm:x:3:4:adm:/var/adm:/sbin/nologin4
lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin5
sync:x:5:0:sync:/sbin:/bin/sync6
shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown7
halt:x:7:0:halt:/sbin:/sbin/halt8
mail:x:8:12:mail:/var/spool/mail:/sbin/nologin9
operator:x:11:0:operator:/root:/sbin/nologin10
111111111
2222222
3333333333
 sed -r '/root/r 1.txt' passwd
	//正则搜寻root,在root后面读取新文件

ps:在当前文件中,读取其他文件的“部分”内容。

写文件内容:w(另存为)

sed -r 'w 111.txt' 1.txt 
//把1.txt全部内容写入111.txt
sed -r '/root/w 123.txt' passwd //把passwd里含有root字段的行写到123.txt

 追加命令:a(之后)

sed -r 'a123' passwd //每行后面都加上123
sed -r '2a123' passwd //第二行后面加上123

 

//插入段落,请使用\转义掉回车,不要忘了分号结束
[root@localhost ~]# sed -r '2a1111\
3333333\
444444' passwd


root:x:0:0:root:/root:/bin/bash1
bin:x:1:1:bin:/bin:/sbin/nologin2
1111
3333333
444444
daemon:x:2:2:daemon:/sbin:/sbin/nologin3
adm:x:3:4:adm:/var/adm:/sbin/nologin4
lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin5
sync:x:5:0:sync:/sbin:/bin/sync6
shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown7
halt:x:7:0:halt:/sbin:/sbin/halt8
mail:x:8:12:mail:/var/spool/mail:/sbin/nologin9
operator:x:11:0:operator:/root:/sbin/nologin10

 插入命令:i(之前)

//在第二行插入新行aaaaaaaaaa

[root@localhost ~]# sed -r '2iaaaaaaaa' passwd 
root:x:0:0:root:/root:/bin/bash1
aaaaaaaa
bin:x:1:1:bin:/bin:/sbin/nologin2
daemon:x:2:2:daemon:/sbin:/sbin/nologin3
adm:x:3:4:adm:/var/adm:/sbin/nologin4
lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin5
sync:x:5:0:sync:/sbin:/bin/sync6
shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown7
halt:x:7:0:halt:/sbin:/sbin/halt8
mail:x:8:12:mail:/var/spool/mail:/sbin/nologin9
operator:x:11:0:operator:/root:/sbin/nologin10

 替换正行命令:c

//把第二行替换成aaaaaaaaa

[root@localhost ~]# sed -r '2caaaaaaaa' passwd 
root:x:0:0:root:/root:/bin/bash1
aaaaaaaa
daemon:x:2:2:daemon:/sbin:/sbin/nologin3
adm:x:3:4:adm:/var/adm:/sbin/nologin4
lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin5
sync:x:5:0:sync:/sbin:/bin/sync6
shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown7
halt:x:7:0:halt:/sbin:/sbin/halt8
mail:x:8:12:mail:/var/spool/mail:/sbin/nologin9
operator:x:11:0:operator:/root:/sbin/nologin10

获取下一行命令:n

//n下一行的意思。
找root行,然后下一行,删除

[root@localhost ~]# sed -r '/root/{n;d}' passwd 
root:x:0:0:root:/root:/bin/bash1
daemon:x:2:2:daemon:/sbin:/sbin/nologin3
adm:x:3:4:adm:/var/adm:/sbin/nologin4
lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin5
sync:x:5:0:sync:/sbin:/bin/sync6
shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown7
halt:x:7:0:halt:/sbin:/sbin/halt8
mail:x:8:12:mail:/var/spool/mail:/sbin/nologin9
operator:x:11:0:operator:/root:/sbin/nologin10

//n:next下一行可以用多次。
[root@localhost ~]# sed -r '/root/{n;n;d}' passwd 
root:x:0:0:root:/root:/bin/bash1
bin:x:1:1:bin:/bin:/sbin/nologin2
adm:x:3:4:adm:/var/adm:/sbin/nologin4
lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin5
sync:x:5:0:sync:/sbin:/bin/sync6
shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown7
halt:x:7:0:halt:/sbin:/sbin/halt8
mail:x:8:12:mail:/var/spool/mail:/sbin/nologin9
operator:x:11:0:operator:/root:/sbin/nologin10

 反向选择:!

 下面两个做对比,一个没有!,一个有!

[root@localhost ~]# sed -r '2,$d' passwd 
root:x:0:0:root:/root:/bin/bash1


[root@localhost ~]# sed -r '2,$!d' passwd 
bin:x:1:1:bin:/bin:/sbin/nologin2
daemon:x:2:2:daemon:/sbin:/sbin/nologin3
adm:x:3:4:adm:/var/adm:/sbin/nologin4
lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin5
sync:x:5:0:sync:/sbin:/bin/sync6
shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown7
halt:x:7:0:halt:/sbin:/sbin/halt8
mail:x:8:12:mail:/var/spool/mail:/sbin/nologin9
operator:x:11:0:operator:/root:/sbin/nologin10

多重编辑:e 

在一个命令后加上-e后可以再跟命令 

[root@localhost ~]# sed -r -e '1,3d' -e '4s/adm/admin/g' passwd 
admin:x:3:4:admin:/var/admin:/sbin/nologin4
lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin5
sync:x:5:0:sync:/sbin:/bin/sync6
shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown7
halt:x:7:0:halt:/sbin:/sbin/halt8
mail:x:8:12:mail:/var/spool/mail:/sbin/nologin9
operator:x:11:0:operator:/root:/sbin/nologin10
//将一到3行删除,将第4行的adm全局替换成admin

暂存空间hHGgx :

图示:

                shell编程之正则表达式_第1张图片 

 暂存和取用命令,h覆盖暂存空间,H追加暂存空间。g覆盖行,G追加行。

四、AWK

awk 是一种编程语言,用于在linux/unix下对文本和数据进行处理。数据可以来自标准输入、一个或多个文件,或其它命令的输出。它支持用户自定义函数和动态正则表达式等先进功能,

awk的处理文本和数据的方式是这样的,它逐行扫描文件,从第一行到最后一行,寻找匹配的特定模式的行,并在这些行上进行你想要的操作。如果没有指定处理动作,则把匹配的行显示到标准输出(屏幕),awk分别代表其作者姓氏的第一个字母。因为它的作者是三个人,分别是Alfred Aho、Peter Weinberger、 Kernighan。

工作原理

# awk -F: '{print $1,$3}' /etc/passwd
(1)awk使用一行作为输入,并将这一行赋给内部变量$0,每一行也可称为一个记录,以换行符结束

(2)然后,行被:(默认为空格或制表符)分解成字段(或域),每个字段存储在已编号的变量中,从$1开始,
最多达100个字段

(3)awk输出之后,将从文件中获取另一行,并将其存储在$0中,覆盖原来的内容,然后将新的字符串分隔
成字段并进行处理。该过程将持续到所有行处理完毕

图示: 

 shell编程之正则表达式_第2张图片

内部变量

FS:输入字段分隔符(默认空格)

[root@slave2 ~]# df -hT
文件系统                类型      容量  已用  可用 已用% 挂载点
devtmpfs                devtmpfs  475M     0  475M    0% /dev
tmpfs                   tmpfs     487M     0  487M    0% /dev/shm
tmpfs                   tmpfs     487M  7.6M  479M    2% /run
tmpfs                   tmpfs     487M     0  487M    0% /sys/fs/cgroup
/dev/mapper/centos-root xfs        17G  3.1G   14G   19% /
/dev/sda1               xfs      1014M  149M  866M   15% /boot
tmpfs                   tmpfs      98M     0   98M    0% /run/user/0
[root@slave2 ~]# df -hT | grep /$  |  awk '{print $5}'
14G
[root@slave2 ~]# df -hT | grep /$  |  awk '{print $5}' | awk 'BEGIN{FS='G'} {print $1}'
1
[root@slave2 ~]# df -hT | grep /$  |  awk '{print $5}' | awk 'BEGIN{FS="G"} {print $1}'
14

OFS:输出字段分隔符  (FS和OFS在一个{}里面)

[root@slave2 ~]# awk 'BEGIN{FS=":";OFS="++++"} {print $1,$2}' /etc/passwd  //以++++来作为分隔
root++++x
bin++++x
daemon++++x
adm++++x
lp++++x
sync++++x
shutdown++++x
halt++++x
mail++++x
operator++++x
games++++x
ftp++++x

RS:输入记录(行)分隔符,默认换行符

[root@slave2 ~]# awk 'BEGIN{RS="a"} {print $0}' 1.txt 
1111111111111111111
2222222222222222222
333333333333333
4444444

111111111111111111
22222222222222222222
33333333333333333333
44444444

ORS:输出记录(行)分隔符,默认换行符

[root@slave2 ~]# awk 'BEGIN{RS="a";ORS="============="} {print $0}' 1.txt 
1111111111111111111
2222222222222222222
333333333333333
4444444=============
111111111111111111
22222222222222222222
33333333333333333333
44444444=============
=============

FNR:多文件独立编号

[root@slave2 ~]# awk '{print FNR,$1}' /etc/passwd  1.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
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
1 1111111111111111111
2 2222222222222222222
3 333333333333333
4 4444444a
5 111111111111111111

NR:多文件汇总编号

[root@slave2 ~]# awk '{print NR,$1}' /etc/passwd  1.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
4 adm:x:3:4:adm:/var/adm:/sbin/nologin
5 lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
6 1111111111111111111
7 2222222222222222222
8 333333333333333
9 4444444a
10 111111111111111111

NF:字段总数

[root@localhost ~]# awk -F: '{print NF, $0}'  /etc/passwd
7 root:x:0:0:root:/root:/bin/bash
7 bin:x:1:1:bin:/bin:/sbin/nologin
7 daemon:x:2:2:daemon:/sbin:/sbin/nologin

[root@localhost ~]# awk -F: '{print NF, $NF}'  /etc/passwd
7 /bin/bash
7 /sbin/nologin
7 /sbin/nologin

格式化输出

print函数

[root@localhost ~]# date |awk '{print "Month: " $2 "\nYear: " $1}'
Month: 11月
Year: 2017年

ps:\n换行符,想输出文字用引号。

[root@localhost ~]# awk -F: '{print "username is: " $1 "\t uid is: " $3}' /etc/passwd | head -1
username is: root	 uid is: 0
[root@localhost ~]# awk -F: '{print "\tusername and uid: " $1,$3 "!"}' /etc/passwd  | head -1
	username and uid: root 0!

printf:

语法 

%s 字符类型
%d 数值类型
%f 浮点型,可以定义保留
占15字符
- 表示左对齐,默认是右对齐
printf默认不会在行尾自动换行,加\n
, 逗号,输出字段分隔符

[root@slave2 ~]# awk -F: '{printf "%-10s %-10s %-15s\n",$1,$2,$3}' /etc/passwd | head
root       x          0              
bin        x          1              
daemon     x          2              
adm        x          3              
lp         x          4              
sync       x          5              
shutdown   x          6              
halt       x          7              
mail       x          8              
operator   x          11             

 在每一列之间增加|,看的更加清晰。

[root@localhost ~]# awk -F: '{printf "|%-15s| %-10s| %-15s|\n", $1,$2,$3}' /etc/passwd | head
|root           | x         | 0              |
|bin            | x         | 1              |
|daemon         | x         | 2              |
|adm            | x         | 3              |
|lp             | x         | 4              |
|sync           | x         | 5              |
|shutdown       | x         | 6              |
|halt           | x         | 7              |
|mail           | x         | 8              |
|operator       | x         | 11             |

模式(正则表达)和动作

① 概念

任何awk语句都由模式和动作组成。模式部分决定动作语句何时触发及触发事件。如果省略模式部分,动作将时刻保持执行状态。每一行都会有动作。模式可以是任何条件语句或复合语句或正则表达式。有模式的话,就是对模式对应的行进行动作。

模式:可以是条件测试,正则,复合语句

动作:可以是打印,计算等。

②字符串比较

awk '/^root/' /etc/passwd
awk '$0 ~/^root/' /etc/passwd
awk '$0!~/^root/' /etc/passwd
awk -F: '$1 ~/^root/' /etc/passwd

③ 数值比较

目的:比较表达式采用对文本进行比较,只有当条件为真,才执行指定的动作。比较表达式使用关系运算符,用于比较数字与字符串。

关系运算符

语法

运算符 含义 示例
<     小于             x <=     小于或等于     x<=y
==     等于             x==y
!=     不等于        x!=y
>=     大于等于         x>=y
>     大于             x>y

示例

# awk -F: '$3 == 0' /etc/passwd 
# awk -F: '$3 == 1' /etc/passwd 
# awk -F: '$3 < 10' /etc/passwd
== 也可以用于字符串判断
# awk -F: '$7 == "/bin/bash"' /etc/passwd
# awk -F: '$1 == "alice"' /etc/passwd

算数 运算

语法
    + - * / %(模) ^(幂2^3) 
示例
    # awk -F: '$3 * 10 > 500' /etc/passwd

④ 多条件

逻辑操作符和复合模式

语法:

&& 逻辑与 a&&b
|| 逻辑或 a||b
! 逻辑非 !a

# awk -F: '$1~/root/ && $3<=15'	 /etc/passwd
# awk -F:	 '$1~/root/ || $3<=15'		 /etc/passwd
# awk -F:	 '!($1~/root/ || $3<=15)' 	/etc/passwd

范围模式:

awk '/从哪里/,/到哪里/'  filename

# awk -F: '/adm/,/lpd/' /etc/passwd
从adm到ldp,显示出来,注意避免匹配重复的字段。

awk脚本编程

① 变量

awk调用变量

自定义内部变量 -v 

awk -v user=root -F: '$1 == user' /etc/passwd
-v定义变量

外部变量 “ ‘ ”

双引号

# var="bash"
# echo "unix script" | awk "{print "123",\"$var\"}"
123 bash
注意 awk调用外部变量时,外部使用双引号,内部也使用双引号,但需要转义内部的双引号

单引号

# var="bash"
# echo "unix script" |awk '{print $1,"'"$var"'"}'
unix  bash
注意使用单引号时,内部需要用双引转义

② 条件和判断

if语句

语法:

{if(表达式){语句;语句;....}}

需求
    如果$3是0,就说他是管理员

awk -F: '{if($3==0) {print $1 " is administrator."}}' /etc/passwd

if...else 语句

 {if(表达式){语句;语句;...}else{语句;语句;...}}
 {if(){}else{}}

 需求

  如果第三列是0,打印该行第一列,否则打印第七列,登录shell

示例 

 awk -F: '{if($3==0){print $1} else {print $7}}' /etc/passwd

  需求
        统计管理员和系统用户数量
    示例    

awk -F: '{if($3==0){count++} else{i++}} END{print "管理员个数: "count ; print "系统用户数: "i}' /etc/passwd

if...else if...else语句

格式

    {if(表达式1){语句;语句;...}else if(表达式2){语句;语句;...}else if(表达式3){语句;语句;...}else{语句;语句;...}}
    if (条件){动作}elseif(条件){动作}else{动作}
    if(){}else if  (){}else if(){}else{}

需求:

    显示出三种用户的信息管理员:管理员ID为0,内置用户:用户ID<1000,普通用户: 用户ID>999

[root@localhost ~]# awk -F:  '{if($3==0){print $1," is admin "}else if ($3>999){print $1," is user"}else {print $1, " is sofo user"}}'  /etc/passwd  

root  is admin 
bin  is sofo user
daemon  is sofo user
adm  is sofo user
lp  is sofo user
sync  is sofo user
shutdown  is sofo user
halt  is sofo user
mail  is sofo user

循环

while 

循环打印10个数字

[root@slave2 ~]# awk 'BEGIN{ while(i<=10){print i;i++}}'

1
2
3
4
5
6
7
8
9
10

第一行打印十次

[root@slave2 ~]# awk -F: '{while(i<=9){print $0;i++}}' /etc/passwd
root:x:0:0:root:/root:/bin/bash
root:x:0:0:root:/root:/bin/bash
root:x:0:0:root:/root:/bin/bash
root:x:0:0:root:/root:/bin/bash
root:x:0:0:root:/root:/bin/bash
root:x:0:0:root:/root:/bin/bash
root:x:0:0:root:/root:/bin/bash
root:x:0:0:root:/root:/bin/bash
root:x:0:0:root:/root:/bin/bash
root:x:0:0:root:/root:/bin/bash

for

循环打印5个数字

[root@slave2 ~]# awk 'BEGIN{for(i=1;i<=5;i++){print i}}'
1
2
3
4
5

每行打印10次

awk -F: '{ for(i=1;i<=10;i++) {print $0} }' /etc/passwd

数组

定义数组

将用户名定义为数组的值,打印第一个值。

[root@slave2 ~]# awk -F: '{username[++i]=$1}  END{print  username[1]}' /etc/passwd
root

数组遍历

按索引遍历

[root@slave2 ~]# awk -F: '{username[++i]=$1}  END{for (i in username) {print i, username[i]}}' /etc/passwd  | sort -n  //sort排序
1 root
2 bin
3 daemon
4 adm
5 lp
6 sync
7 shutdown
8 halt

 

你可能感兴趣的:(linux,正则表达式,运维,centos)