什么是正则表达式
简单的说,正则表达式就是处理字串的方法,他是以行为单位来进行字串的处理行为, 正则表达式通过一些特殊符号的辅助,可以让使用者轻易的达到“搜寻/删除/取代”某特定字串的处理程序!
正则表达式基本上是一种“表达式”, 只要工具程序支持这种表达式,那么该工具程序就可以用来作为正则表达式的字串处理之用。 例如 vi, grep, awk ,sed 等等工具,因为她们有支持正则表达式, 所以,这些工具就可以使用正则表达式的特殊字符来进行字串的处理。但例如 cp, ls 等指令并未支持正则表达式, 所以就只能使用 Bash 自己本身的通配符而已。
是 Linux 基础当中的基础,如果学成了之后,一定是“大大的有帮助”的!这就好像是金庸小说里面的学武难关:任督二脉! 打通任督二脉之后,武功立刻成倍成长
关于语系
在英文大小写的编码顺序中,zh_TW.big5 及 C 这两种语系的输出结果分别如下:
LANG=C 时:0 1 2 3 4 ... A B C D ... Z a b c d ...z
LANG=zh_TW 时:0 1 2 3 4 ... a A b B c C d D ... z Z
特殊符号 | 代表意义 |
---|---|
[:alnum:] | 代表英文大小写字符及数字,亦即0-9, A-Z, a-z |
[:alpha:] | 代表任何英文大小写字符,亦即A-Z, a-z |
[:blank:] | 代表空格键与[Tab]按键两者 |
[:cntrl:] | 代表键盘上面的控制按键,亦即包括CR, LF, Tab, Del..等等 |
[:digit] | 代表数字而已,亦即0-9 |
[:graph:] | 除了空格符(空格键与[Tab]按键)外的其他所有按键 |
[:lower:] | 代表小写字符,亦即a-z |
[:print:] | 代表任何可以被打印出来的字符 |
[:punct:] | 代表标点符号(punctuation symbol),亦即:"'?!;:#5$.. |
[:upper:] | 代表大写字符,亦即A-Z |
[:space:] | 任何会产生空白的字符,包括空格键,[Tab], CR等等 |
[:xdigit:] | 代表16进位的数字类型,因此包括: 0-9, A-F, a-f的数字与字符 |
示例:数据来源于鸟哥私房菜
[root@localhost ~]# vim niaoge.txt
[root@localhost ~]# cat niaoge.txt
"Open Source" is a good mechanism to develop programs.
apple is my favorite food.
Football game is not use feet only.
this dress doesn't fit me.
However, this dress is about $ 3183 dollars.
GNU is free air not free beer.
Her hair is very beauty.
I can't finish the test.
Oh! The soup taste good.
motorcycle is cheap than car.
This window is clear.
the symbol '*' is represented as start.
Oh! My god!
The gd software is a library for drafting programs.
You are the best is mean you are the no. 1.
The world <Happy> is the same with "glad".
I like dog.
google is the best tools for search keyword.
goooooogle yes!
go! go! Let's go.
# I am VBird
示例:
[root@localhost ~]# grep "[[:alnum:]]" niaoge.txt /匹配alnum
[root@localhost ~]# grep "[[:digit:]]" niaoge.txt /匹配digit
RE字符 | 意义 | |
---|---|---|
1 | ^word | 意义:待搜寻的字符串(word)在行首! |
2 | word$ | 意义:待搜寻的字符串(word)在行尾! |
3 | . | 意义:代表「一定有一个任意字符」的字符! |
4 | \ | 意义:跳脱字符,将特殊符号的特殊意义去除! |
5 | * | 意义:重复零个到无穷多个的前一个RE字符 ! |
6 | [list] | 意义:字符集合的RE字符,里面列出想要撷取的字符! |
7 | [n1-n2] | 意义:字符集合的RE字符,里面列出想要撷取的字符范围! |
8 | [^list] | 意义:字符集合的RE字符,里面列出不要的字符串或范围! |
9 | \{n,m\} | 意义:连续n到m个的「前一个RE字符」! 意义:若是\{n,\}则是连续n个以上的前一个RE字符! |
示例:
-n显示行数
-o按字段分行
1. 搜寻行首为#开始的行,并列出行号
[root@localhost ~]# grep -n '^#' niaoge.txt
2. 搜寻行尾为!结束的行,并列出行号
[root@localhost ~]# grep -n '!$' niaoge.txt
3. 搜寻的字符串可以是(eve) (eae) (eee) (ee),但不能仅有 (ee) 亦即e与e中间「一定」仅有一个字符,空格符也是字符
[root@localhost ~]# grep -n 'e.e' niaoge.txt
4. 搜寻含有单引号的行
[root@localhost ~]# grep -n \' niaoge.txt
5. 找出含有(es) (ess) (esss)等等的字符串,注意,因为 * 可以是0个,所以 es 也符合,另外,因为 * 为重复
「前一个RE字符」的符号,因此,在 * 之前必须要紧接着一个RE字符喔,例如任意字符则为 .*
[root@localhost ~]# grep -n 'ess*' niaoge.txt
6. 搜寻含有(gl)或(gd)的那一行,需要特别留意的是,在[]当中「谨代表一个待搜寻的字符」,
例如 g[ld] 代表搜寻的字符串可以是 gl或gd 即 [ld] 代表 l 或 d 的意思
[root@localhost ~]# grep -n 'g[ld]' niaoge.txt
7. 搜寻含有任意数字的那一行,在字符集合 [] 中的减号 - 代表两个字符之间的所有连续字符,例如所有大写字符则为 [A-Z]
[root@localhost ~]# grep -n '[0-9]' niaoge.txt
8. 搜寻的字符串可以是 (oog) (ood) 但不能是 (oot) ,那个 ^ 在 [] 内时,代表的意义是「反向选择」的意思。
[root@localhost ~]# grep -n 'oo[^t]' niaoge.txt
9. 在g与g之间有2个到3个的 o 存在的字符串,亦即 (goog) (gooog)
[root@localhost ~]# grep -n 'go\{2,3\}g' niaoge.txt
匹配 2 个连续的 o 字符
[root@localhost ~]# grep -n 'go\{2\}g' niaoge.txt
匹配 2个以上连续的 o 字符
[root@localhost ~]# grep -n 'go\{2,\}g' niaoge.txt
匹配 3 个以下连续的 o 字符
[root@localhost ~]# grep -n 'go\{,3\}g' niaoge.txt
grep进阶
-A n 把匹配成功行之后的n行也同时列出。 A 就是 after 的首字母
就是 之后 的意思
-B n 把匹配成功行之前的n行也同时列出。B 就是 before 的首字母
就是 之前 的意思
符号 ^ 在 [] 内时是取反的意思,在 [] 之外是行首的意思
. 代表一个任意字符
* 代表重复零到多个在 其前面的一个字符
.* 代表零个或多个任意字符
示例:
- 显示 /etc/passwd 含有 mail 的行及其前2行和后 3 行
[root@localhost ~]# grep mail -B 2 -A3 /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
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
- 显示 目标行(这里是含有 mail 字符)的 前 后 各 3 行
[root@localhost ~]# grep mail -C 3 /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
games:x:12:100:games:/usr/games:/sbin/nologin
ftp:x:14:50:FTP User:/var/ftp:/sbin/nologi
- 只显示匹配到的字符
[root@localhost ~]# grep -o 'nologin' /etc/passwd
加上统计数量
[root@localhost ~]# grep -o -c 'nologin' /etc/passwd
只要文件名
[root@localhost ~]# grep -l 'nologin' /etc/passwd
递归查找,就是在一个目录下查找
[root@localhost ~]# grep -r 'nologin' /etc/
- 搜索 test 或 tast
[root@localhost ~]# grep -n 't[ae]st' niaoge.txt
- 搜索 oo 但其前面不要有g
[root@localhost ~]# grep -n '[^g]oo' niaoge.txt
注意:当搜索的行内含有符合搜索条件的字段时,此行就会忽略明确不要的条件,比如以上的例子就可能会搜索到下面的内容
3:tool is a good tool
8:goooooogle
- 显示 oo 前面非小写字符的行
[root@localhost ~]# grep -n ‘[^a-z]oo’ niaoge.txt 方法一
[root@localhost ~]# grep -n ‘[^[:lower:]]oo’ niaoge.txt 方法二
- 显示开头不是英文字符的行
[root@localhost ~]# grep -n ‘^[^[:alpha]]’ niaoge.txt
- 显示行首不是 # 和 ; 的行
[root@localhost ~]# grep '^[^#;]' niaoge.txt
- 找到以 . 结尾的行
[root@localhost ~]# grep -n ‘\.$’ niaoge.txt 需要用 \ 进行转意
- 查找开头是 g 和结尾也是 g 的行,中间的字符可有可无
[root@localhost ~]# grep -n 'g.*g' niaoge.txt
- 查找以 a 为开头的任意文件名
[root@localhost ~]# ls -l a* 方法一
[root@localhost ~]# ls |grep -n ‘^a.*’ 方法二
- 列出 /etc 目录下的链接文件
[root@localhost ~]# ls -l /etc |grep ‘^l’
再统计一下多少个
[root@localhost ~]# ls -l /etc |grep ‘^l’ |wc -l
扩展正则
RE字符 | 意义 | |
---|---|---|
1 | + | 意义:重复了「一个或一个以上」的前一个RE字符 |
2 | ? | 意义:「零个或一个」的前一个RE字符 |
3 | | | 意义:用或( or )的方式找出数个字串 |
4 | () | 意义:找出「群组」字串 |
5 | ()+ | 意义:多个重复群组的判别 |
示例:
1. 搜寻 (god) (good) (goood)...等等的字串。那个0+「代表一个以上的o」
[root@localhost ~]# egrep -n 'go+d' niaoge.txt
2. 搜寻 (gd) (god) 这两个字串。那个 o?「代表空的或1个o」
[root@localhost ~]# egrep -n 'go?d' niaoge.txt
3. 搜寻 gd 或 good 这两个字串,那如果还想要找出dog呢?
[root@localhost ~]# egrep -n 'gdlgood' niaoge.txt
[root@localhost ~]# egrep -n 'gdlgoodldog' niaoge.txt
4. 搜寻 (glad) 或 (good) 这两个字串,因为 g 与 d 是重复的,所以,可以将 la 与 oo 列於()当中,并以|分隔开来
[root@localhost ~]# egrep -n 'g(laloo)d' niaoge.txt
5. 将「AxyzxyzxyzxyzC」用echo叫出,然后再使用如下的方法搜寻
[root@localhost ~]# echo 'AxyzxyzxyzxyzC'| egrep 'A(xyz)+C'
上面的例子意思是说,我要找开头是A结尾是C,
中间有一个以上的"xyz" 字串的意思~
支持扩展正则的工具
grep -E
egrep
sed
awk
关于 分组 小括号 () 的深入理解
写出匹配日期格式 YYYY-MM-DD 的正则表达式
[root@localhost ~]# echo "2019-12-30" |grep -E '[1-9][0-9]{3}-((0[1-9])|(1[0-2]))-((0[1-9])|([12][0-9])|(3[01]))'
2019-12-30
[root@localhost ~]# echo "1919-12-30" |grep -E '[1-9][0-9]{3}-((0[1-9])|(1[0-2]))-((0[1-9])|([12][0-9])|(3[01]))'
1919-12-30
{3}代表后三位都是同一个参数
正则高级部分: 贪婪|非贪婪
贪婪 就是尽可能的多匹配
非贪婪 就是尽可能的少匹配,只需要在一些表示量词(就是次数)的后面加上?
比如:.*?
+?
grep 实现非贪婪
grep 或者 egrep 默认都是贪婪模式,不支持非贪婪模式。
要想实现非贪婪需要使用 -P 参数,这会使用 Perl 语言环境的正则
示例:
[root@localhost ~]# echo 'a1b22222222b' |grep 'a.*b' #默认贪婪
a1b222222226
[root@localhost ~]# echo 'a1b22222222b' |grep -E 'a.*b' #默认贪婪
a1b2222222b
[root@localhost ~]# echo 'a1b22222222b' |egrep 'a.*?b' #不支持非贪婪
a1b22222222b
[root@localhost ~]# echo 'a1b22222222b' |grep -P 'a.*?b' #支持非贪婪
a1b222222226
Perl 语言
\w 表示任意 一个 大小写字母 [a-zA-Z] 、下划线 _ 和数字 [0-9]
\d 表示任意 一个 数字 [0-9]
当然这些规则适用于大部分的 编程语言,比如 python java javascript go php 等
[root@localhost ~]# echo 'abc_-123'|grep -P '\w'
abc_-123
[root@localhost ~]# echo 'abc_-123'|grep -P -o '\w'
a
b
c
_
1
2
3