Shell元字符(正则表达式)及其用法详解
基础元字符
我们先来看看到底有哪些基础元字符,如表 1 所示。元字符 | 作 用 |
---|---|
* | 前一个字符匹配 0 次或任意多次 |
. | 匹配除换行符外的任意一个字符 |
^ | 匹配行首。例如,^hello 会匹配以 hello 开头的行 |
$ | 匹配行尾。例如,hello& 会匹配以 hello 结尾的行 |
[] | 匹配屮柄号屮指定的任意一个字符,而且只匹配一个字符。例如.[aoeiu]匹配任意一个元音字母, [0-9] 匹配任意一位数字,[a-z][0-9] 匹配由小写字母和一位数字构成的两位字符 |
[^] | 匹配除中括号中的字符以外的任意一个字符。例如,[^0-9] 匹配任意一位非数字字符,[^a-z] 匹配任意一位非小写字母 |
\ | 转义符,用于取消特殊符号的含义 |
\{n\} | 表示其前面的字符恰好出现 n 次。例如,[0-9]\{4\} 匹配4位数字,[1][3-8][0-9]\{9\} 匹配手机号码 |
\(n,\} | 表示其前面的字符出现不少于 n 次。例如,[0-9]\{2,\} 匹配两位及以上的数字 |
\{n,m\} | 表示其前面的字符至少出现 n 次,最多出现 m 次。例如,[a-z]\{6,8\} 匹配 6〜8 位的小写字母 |
下面举例来说明这些基础元字符的作用。我们已经学习过的 grep 命令支持正则表达式,所以下面的练习都需要利用 grep 命令来演示。在使用 grep 命令开始练习之前,建议大家在 ~/.bashrc 文件中建立这个别名,如下:
[root@localhost ~】# vi /root/.bashrc
alias grep='grep --color=auto'
练习文件建立
既然正则表达式是用来在文件中匹配字符串的,那么我们必须建立一个测试用的文件,才可以进行后续的实验。文件如下:
[root@localhost ~]#vi test_rule.txt
Mr. Li Ming said:
he was the most honest man in LampBrother.
123despise him.
But since Mr. shen Chao came,
he never saaaid those words.
5555nice!
because,actuaaaally,
Mr. Shen Chao is the most honest man Later,Mr. Li ming soid his hot body.
"*"前一个字符匹配0次或任意多次
注意,"*"和通配符中的"*"含义不同,它代表前一个字符重复 0 次或任意多次。比如,"a*"并不是匹配"a"后面的任意字符,而是可以匹配所有内容,包括空白行。我们试试:
[root@localhost ~]# grep "a*" test_rule.txt
Mr. Li Ming said:
he was the most honest man in LampBrother.
123despise him.
But since Mr. shen Chao came, he never saaaid those words.
5555nice!
because,actuaaaally,
Mr. Shen Chao is the most honest man
Later,Mr. Li ming soid his hot body.
如果这样写正则表达式"aa*",则代表这行字符串一定要有一个 a,但是后面有没有 a 都可以。也就是说,会匹配至少包含一个 a 的行。
[root@localhost ~]# grep "aa*" test_rule.txt Mr. Li Ming said:
he was the most honest man in LampBrother. But since Mr. shen Chao came, he never saaaid those words. because,actuaaaally,
Mr. Shen Chao is the most honest man Later,Mr. Li ming soid his hot body
[root@localhost ~]# grep "aaa*" test_rule.txt
he never saaaid those words.
because,actuaaaally,
[root@localhost ~]# grep "aaaaa*" test_rule.txt
because,actuaaaally,
"."匹配除换行符外的任意一个字符
正则表达式"."只能匹配一个字符,这个字符可以是任意字符。举个例子:
[root@localhost ~]# grep "s..d" test_rule.txt
Mr. Li Ming said:
Later,Mr. Li ming soid his hot body.
# "s..d"会匹配在s和d这两个字母之间一定有两个字符的单词
[root@localhost ~]# grep "s.*d" test_rule.txt
Mr. Li Ming said:
he never saaaid those words.
Later,Mr. Li ming soid his hot body.
#最后一句话比较有意思,匹配的是"soid his hot bod"
[root@localhost ~]# grep ".*" test_rule.txt
Mr. Li Ming said:
he was the most honest man in LampBrother.
123despise him.
But since Mr. shen Chao came,
he never saaaid those words.
5555nice!
because,actuaaaally,
Mr. Shen Chao is the most honest man
Later,Mr. Li ming soid his hot body
"^"匹配行首,"$"匹配行尾
"^"代表匹配行首,比如"^M"会匹配以大写"M"开头的行。
[root@localhost ~]# grep "^M" test_rule.txt
Mr. Li Ming said:
Mr. Shen Chao is the most honest man
[root@localhost ~]# grep "n$" test_rule.txt
Mr. Shen Chao is the most honest man
那怎么解决呢?也很简单,执行命令"dos2unix 文件名"把文档格式转换为 Linux 格式即可。如果没有这个命令,则只需安装 dos2unix 这个 RPM 包即可。
而"^$"则会匹配空白行。
[root@localhost ~]# grep -n "^$" test_rule.txt
4:
8:
11:
"[]"匹配中括号中指定的任意一个字符,且只匹配一个字符
"[]"会匹配中括号中指定的任意一个字符,注意只能匹配一个字符。比如 [ao] 要么匹配 a 字符,要么匹配一个 o 字符。
[root@localhost ~]# grep "s[ao]id" test_rule.txt
Mr. Li Ming said:
Later,Mr. Li ming soid his hot body.
而"[0-9]"会匹配任意一个数字,例如:
[root@localhost ~]# grep "[0-9]" test_rule.txt 123despise him.
5555nice!
#列出包含有数字的行
[root@localhost ~]# grep "[A-Z|" test_rule.txt
Mr. Li Ming said:
he was the most honest man in LampBrother.
But since Mr. shen Chao came,
Mr. Shen Chao is the most honest man
Later,Mr. Li ming soid his hot body.
#列出包含大写字母的行
[root@localhost ~]# grep "^[a-z]" test_rule.txt
he was the most honest man in LampBrother.
he never saaaid those words.
because,actuaaaally,
"[^]"匹配除中括号的字符以外的任意一个字符
这里需要注意,如果"^"在 [] 外,则代表的是行首;如果在 [] 内,则代表的是取反。比如"^[a-z]"会匹配以小写字母开头的行,而"^[A-z]"会匹配不以小写字母开头的行。
[root@localhost ~]# grep "^[^a-z]" test_rule.txt
Mr. Li Ming said:
123despise him.
But since Mr. shen Chao came,
5555nice!
Mr. Shen Chao is the most honest man Later,Mr. Li ming soid his hot body.
[root@localhost ~]# grep "^[^a-zA-Z]" test_rule.txt 123despise him.
5555nice!
"\"转义符
转义符会取消特殊符号的含义。如果想要匹配使用"."结尾的行,那么正则表达式是".$"是不行的,因为"."在正则表达式中有特殊含义,代表任意一个字符。所以需要在前面加入转义符,如"\.$"。
[root@localhost ~]# grep "\.$" test_rule.txt
he was the most honest man in LampBrother.
123despise him.
he never saaaid those words.
Later,Mr. Li ming soid his hot body.
"\{n\}"表示其前面的字符恰好出现 n 次
"\{n\}"中的 n 代表数字,这个正则表达式会匹配前一个字符恰好出现 n 次的字符串,比如"zo\{3\}m"只能匹配"zooom"这个字符串。例如,"a\{3\}"就会匹配 a 字母连续出现 3 次的字符串。
[root@localhost ~]# grep "a\{3\}" test_rule.txt
he never saaaid those words,
because,actuaaaally,
[root@localhost ~]# grep "[su]a\{3\}[il]" test_rule.txt
he never saaaid those words.
#只匹配3个连续的a
[root@localhost ~]# grep "[su]a\{4\}[il]" test_rule.txt because,actuaaaally,
# 只匹配4个连续的a
[root@localhost ~]# grep "[0-9]\{3\}" test_rule.txt
123despise him.
5555nice!
[root@localhost -]# grep "^[0-9]\{3\}[a-z]" test_mle.txt
123despise him.
#只匹配以连续三个数字开头的行
[root@localhost ~]# grep "^[0-9]\{4\}[a-z]"test_mle.txt
5555nice!
#只匹配以连续四个数字开头的行
"\{n,\}"表示其前面的字符出现不少于 n 次
"\{n,\}"会匹配前面的字符出现最少n次的字符串。比如"zo\{3,\}m"这个正则表达式就会匹配在字母 z 和 m 之间最少有三个 o 的字符串。那么"^[(0-9]\{3,\}[a-z]"这个正则表达式就能匹配最少连续 3 个数字开头的字符串。
[root@localhost ~]# grep "^[0-9]\{3,\}[a-z]" test_rule.txt
123despise him.
5555nice!
#匹配最少以连续三个数字开头的行
[root@localhost ~]# grep "[su]a\{3,\}[il]" test_mle.txt
he never saaaid those words, because,actuaaaaly,
#匹配在字母 s 或 u 和 i 或 l 之间最少出现 3 个连续的 a 的字符串
"\{n,m\}"表示其前面的字符至少出现n次,最多出现m次
"\{n,m\}"会匹配前一^字符最少出现 n 次、最多出现 m 次的字符串,比如"\{1,3\}"能够匹配字符串"zom"、"zoom"和"zooom"。还是用我们的例子文件做实验:
[root@localhost ~]# grep "sa\{1,3\}i" test_rule.txt
Mr. Li Ming said:
he never saaaid those words.
#匹配在字母s和字母i之间最少有一个a、最多有3个a的字符串
[root@localhost ~]# grep "sa\{2,3\}i" test_rule.txt
he never saaaid those words.
#匹配在字母s和字母i之间最少有两个a、最多有3个a的字符串
扩展正则表达式
熟悉正则表达式的人应该很疑惑,在正则表达式中应该还可以支持一些元字符,比如"+"、"?"、"|"、"()"。其实 Linux 是支持这些元字符的,只是 grep 命令默认不支持而已。如果要想支持这些元字符,则必须使用 egrep 或 grep -E 命令,所以我们又把这些元字符称作扩展元字符。
如果査询 grep 命令的帮助,对 egrep 的说明就是和 grep -E 一样的命令,所以我们可以把这两个命令当作别名来对待。通过表 2 来看看 Shell 中支持的扩展元字符。
扩展元字符 | 作 用 |
---|---|
+ |
前一个字符匹配 1 次或任意多次。 如“go+gle”会匹配“gogle” “google”或“gooogle”。当然,如果“o”有更多个,则也能匹配 |
? |
前一个字符匹配 0 次或 1 次。 如 “colou?r” 可以匹配 “colour” 或 “color” |
| |
匹配两个或多个分支选择。 如“was|his”既会匹配包含“was”的行,也会匹配包含“his”的行 |
() |
匹配其整体为一个字符,即模式单元。可以理解为由多个单个字符组成的大字符。 如“(dog)+”会匹配“dog” “dogdog” “dogdogdog”等,因为被()包含的字符会被当成一个整体。但 “hello(world|earth)” 会匹配 “hello world” 及 “hello earth” |
所有教程
- C语言入门
- C语言编译器
- C语言项目案例
- 数据结构
- C++
- STL
- C++11
- socket
- GCC
- GDB
- Makefile
- OpenCV
- Qt教程
- Unity 3D
- UE4
- 游戏引擎
- Python
- Python并发编程
- TensorFlow
- Django
- NumPy
- Linux
- Shell
- Java教程
- 设计模式
- Java Swing
- Servlet
- JSP教程
- Struts2
- Maven
- Spring
- Spring MVC
- Spring Boot
- Spring Cloud
- Hibernate
- Mybatis
- MySQL教程
- MySQL函数
- NoSQL
- Redis
- MongoDB
- HBase
- Go语言
- C#
- MATLAB
- JavaScript
- Bootstrap
- HTML
- CSS教程
- PHP
- 汇编语言
- TCP/IP
- vi命令
- Android教程
- 区块链
- Docker
- 大数据
- 云计算