Shell 正则表达式

什么是正则表达式

简单的说,正则表达式就是处理字串的方法,他是以行为单位来进行字串的处理行为, 正则表达式通过一些特殊符号的辅助,可以让使用者轻易的达到“搜寻/删除/取代”某特定字串的处理程序!

正则表达式基本上是一种“表达式”, 只要工具程序支持这种表达式,那么该工具程序就可以用来作为正则表达式的字串处理之用。 例如 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
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 219,427评论 6 508
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,551评论 3 395
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 165,747评论 0 356
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,939评论 1 295
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,955评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,737评论 1 305
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,448评论 3 420
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,352评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,834评论 1 317
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,992评论 3 338
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,133评论 1 351
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,815评论 5 346
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,477评论 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 32,022评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,147评论 1 272
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,398评论 3 373
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,077评论 2 355