第四章 正则表达式
什么是正则表达式
在编写处理字符串的程序或网页时,经常会有查找符合某些复杂规则的字符串的需要。正则表达式就是用于描述这些规则的工具口换句话说,正则表达式就是记录文本规则的代码。
正则表达式的广泛应用
正则表达式在unix/linux系统中得到广泛的应用,强化了工具本身的功能。常见的UNIX下支持正则表达式的工具有:
》用于匹配文本行的grep工具族:
》用于改变输入流的sed流编辑器(streamediter);
》用于处理字符串的语言,如awk, python,perl, tcl等语言;
》文件查看程序,或分页程序,如mare. page, less等。
》文本编辑器,如ed, vi,emacs, vim等·
如何学习正则表达式
实例一
匹配当前存在 file单词并且在这个单词后还有一个file的句子
\bfile\b.*\bfile\b
Copy一段
假如你要找的是hi后面不远处跟着一个Lucy,你应该用\bhi\b.*\bLucy\b。
这里,.是另一个元字符,匹配除了换行符以外的任意字符。*同样是元字符,不过它代表的不是字符,也不是位置,而是数量——它指定*前边的内容可以连续重复使用任意次以使整个表达式得到匹配。因此,.*连在一起就意味着任意数量的不包含换行的字符。现在\bhi\b.*\bLucy\b的意思就很明显了:先是一个单词hi,然后是任意个任意字符(但不能是换行),最后是Lucy这个单词。
换行符就是'\n',ASCII编码为10(十六进制0x0A)的字符。
如果同时使用其它元字符,我们就能构造出功能更强大的正则表达式。比如下面这个例子:
0\d\d-\d\d\d\d\d\d\d\d匹配这样的字符串:以0开头,然后是两个数字,然后是一个连字号“-”,最后是8个数字(也就是中国的电话号码。当然,这个例子只能匹配区号为3位的情形)。
这里的\d是个新的元字符,匹配一位数字(0,或1,或2,或……)。-不是元字符,只匹配它本身——连字符(或者减号,或者中横线,或者随你怎么称呼它)。
为了避免那么多烦人的重复,我们也可以这样写这个表达式:0\d{2}-\d{8}。这里\d后面的{2}({8})的意思是前面\d必须连续重复匹配2次(8次)。
如果需要更精确的说法,\b匹配这样的位置:它的前一个字符和后一个字符不全是(一个是,一个不是或不存在)\w。
如何实践正则表达式
我们不是机器,总会犯错误。一般情况下,正则表达式不可能一次写正确。这就需要我们不断修改正则表达式,不断通近那个正确的写法,直到恰好达到我们想要的目的。
NOTE
历史上曾经出现过3种grep,可以用于匹配文本。它们是:
Grep 最早的文本匹配程序。使用PQSIX支持的基本正则表达式(Basic Regular Expression, BRE )
Egrep 扩展的grep(Extend grep)。使用扩展正则表达式〔Extended Regular Expression, ERE )
Fgrep 快速grep( Fast grep)。这个版本用于匹配固定字符串而不是正则表达式。
在I942年发布的PDS1X标准中,3个prep版本合而为一,POSIX可以通过参数来支持多个正则表达式模式,无论是BRE还是ERE,fgrep和egrep还是可以在所有的unix/inux系统上使用,但是被标记为deprecated(不推荐〕
正则基础
元字符
正则表达式是描述某种匹配规则的工具。
正则中有两种字符一种基本字符(没有任何意义),一种元字符(赋予了表达匹配的某些含义)
POSIXBRE和ERE都支持的meta字符
^
|
BRE,ERE
|
锚定行或者字符串的开始,如"^grep" 匹配所有以grep开头的行。
BRE:仅在正则表达式结尾处具有特殊含义;
ERE:在正则表达式的任何地方都有特殊含义。
|
$
|
BRE,ERE
|
锚定行或者字符串的结束,如"grep$" 匹配所有以grep结束的行。
BRE:仅在正则表达式结尾处具有特殊含义;
ERE:在正则表达式的任何地方都有特殊含义。
|
.
|
BRE,ERE
|
匹配一个非换行的任何单个字符(除NUL)。
如:‘gr.p'匹配gr后加一个任意字符后,然后p
|
*
|
BRE,ERE
|
匹配其前的任何数目或没有的单个字符,
例: . 表示任一字符, 则 .* 匹配任一字符的任意长度
|
[]
|
BRE,ERE
|
匹配方括号内的任一字符,其中可用连字符(-)指的连续字符的范围
;^符号苦出现在方括号的第一个位置,则表示匹配不在列表中的任一字符,
|
POSIXBRE中才有的字符:
\{n,m\}
|
区间表达式,匹配在它前面的单个字符重现的次数区别。
\{n\}指重现n次;\{n,m\}指重现n至m次;
|
\( \)
|
保留空间,可以将最多9个独立的子模式存储在单个模式中。
如\(ab\).*\1 : 指匹配ab组合的两次重现,中间可存在任意数目的字符。
|
\n
|
重复在\(与\)方括号内第n个子模式至此点的模式。
|
POSIXERE中才有的字符:
{n,m}
|
与BRE的\{n,m\}功能相同
|
+
|
匹配前面正则表达式的一个或多个扩展
|
?
|
匹配前面正则表达式的零个或一个扩展
|
|
|
匹配|符号前或后的正则表达式
|
( )
|
匹配方括号括起来的正则表达式群
|
Grep程序支持的meta字符plus
\<
|
锚定单词的开始,如:“\<grep” 匹配以grep开头的单词的行
|
\>
|
锚定单词的结束,
如:“grep\>”匹配包含以grep结尾的单词的行
|
\w
|
匹配文字和数字字符.也就是[A-Za-z0-9],
如’G\w*p‘匹配以G后跟零个或多个文字或数字字符.然后是p
|
\W
|
\w的反之形式,匹配一个或多个非单词字符,如点号、句号等
|
\b
|
单词锁定符,如:\bgrep\b只匹配grep
|
实例
//只显示以a开头的文件
[houchangren@ebsdi-23260-oozie shell]$ ls |grep '^a'
add.sh
a.sh
//显示a开头的文件中包含hadoop的行
[houchangren@ebsdi-23260-oozie shell]$grep 'hadoop' a*
a.sh:HADOOP_IN_PATH="/usr/lib/hadoop/bin/hadoop"
a.sh:HADOOP=$HADOOP_HOME/bin/hadoop
//显示a.sh文件中包含hadoop的行
[houchangren@ebsdi-23260-oozie shell]$grep 'hadoop' a.sh
HADOOP_IN_PATH="/usr/lib/hadoop/bin/hadoop"
HADOOP=$HADOOP_HOME/bin/hadoop
//显示连续五个a-z的字符在一行的行
[houchangren@ebsdi-23260-oozie shell]$ grep'[a-z]\{5\}' a.sh
HADOOP_IN_PATH="/usr/lib/hadoop/bin/hadoop"
HADOOP_DIR=`dirname "$HADOOP_IN_PATH"`/..
HADOOP=$HADOOP_HOME/bin/hadoop
HADOOP_VERSION=$($HADOOP version | awk '{if(NR == 1) {print $2;}}');
//显示如果test被匹配,es就被存储到内存中,并标记为1.然后搜索任意个字符(.*),这些字符后面跟着另外一个es (\1),找到就显示该行。\1是取占位括号中的值。
[houchangren@ebsdi-23260-oozie shell]$ cata.txt
I'm test; test;
so you don't worry!
[houchangren@ebsdi-23260-oozie shell]$ grep't\(es\)t.*\1' a.txt
I'm test; test;
为了在不同国家的字符编码中保持一至,POSIX(The PortableOperating System Interface)增加了特殊的字符类,如[:alnum:]是A-Za-z0-9的另·个写法。要把它们放到[]号内才能成为正则表达式,如[A-Za-z0-9]或[[:alnum: ]] 在Linux下的grep除fgrap外,都支持POSIX的字符类。方括号表达式除了上面提到的字符外,还支持其他的组成形式:
1. posix字符集
[:alnum:]
|
文字数字字符
|
[:alpha:]
|
文字字符
|
[:blank:]
|
空格与定位字符
|
[:cntrl:]
|
控制字符
|
[:digit:]
|
数字字符
|
[:graph:]
|
非空格字符
|
[:lower:]
|
小写字母字符
|
[:print:]
|
可显示的字符
|
[:punct:]
|
标点符号字符
|
[:space:]
|
空格字符
|
[:upper:]
|
大写字母字符
|
[:xdigit:]
|
16进制数字
|
2.排序符号
指将多个字符视为一个符号,如[.cn.]即将cn视为一个符号
3. 等价字符集
认为多个字符相等,如[=e=]在法文的locale里,可匹配于多种与e相似的字符
正则表达式允许将POSIX字符集与其他字符集混用。如[[:alpha:]!]匹配任意一个英文字母或者感叹号(!)。
//匹配或者数字或者!
[houchangren@ebsdi-23260-oozie shell]$ grep -E'[[:digit:]!]+' a.txt
so you don't worry!
单个字符
匹配单个字符的方式有4种:一般字符、转义的meta字符、.(点号)meta字符,和方括号表达式。
1.一般字符
例如:abc 就是 匹配abc
2.转义的meta字符
例如:\*匹配 * \[\] 匹配[]
3..(点号)字符
例如: .bc 匹配 abc,dbc等等
4.方括号表达式
例如:[cC]hina 只匹配 china 和Chnia
[^abc]d 匹配除了abc之外的任何小写字母
单个表达式匹配多个字符
文本的匹配锚点
^ 和& 开头和结尾的表示
运算符优先级
BRE的运算优先
运算符
|
含义
|
[..][==][::]
|
方括号符号
|
\meta
|
转义的meta字符
|
[]
|
方括号表达式
|
\(\)\n
|
后向引用表达式
|
*\{\}
|
区间表达式和星号表达式
|
无符号
|
连续
|
^&
|
锚点
|
ERE的运算优先
运算符
|
含义
|
[..][==][::]
|
方括号符号
|
\meta
|
转义的meta字符
|
[]
|
方括号表达式
|
()
|
分组
|
*+?{}
|
重置前置的正则表达式
|
无符号
|
连续
|
^&
|
锚点
|
|
|
交替
|
更多差异
1.向后引用
BRE中提供了一种机制名为“后向引用”backreferences,含义是:匹配的是之前正则表达式选定的部分。我们使用\1一\19来引用之前选定的模式,使用\(和\)括起想要之后引用的部分。
例如:
\(go\).*\1匹配一行中前后出现两个go
2.交替
交替是ERE才一有的特性。当使用方括号表达式时,表示可以“匹配这个字符,或者那个字符”,但是无法“匹配这个字符序列或那个字符序列”。当我们需要这个功能时,在ERE中,就用到交替.交替是在不同序列之间用管道符号隔开。例如,you|me匹配you或者me.
交替字符可以和管道符号一样,在一个正则表达式中使用多个来提供多种选择。因为交替字符的优先级最低,所以会一直扩展到新的交替字符,或正则表达式结束为止。
3.分组
在BRE中,我们使用一些meta字符修饰前置字符,匹配重复的情况。但是这样的操作仅仅
针对单个字符。在ERE中,分组功能能够计meta字符修饰前置字符串。分组符号就是使用(和)
将式子括起来。例如〔go)+匹配一个或多个连续的go.
在使用交替时,分组就非常有用。例如:(Lily|Lucy) will visit my house today.在这个正则表达式中,分组限定了访问我家的是Lily或者是Lucy。
正则表达式的应用
正则表达式之所以如此重要,一个原因是许多程序(包括UNIX/linux下的,和Win下的)
都使用正则表达式为自己提供扩展,以支持更强大的功能。
正则表达式的风格有两种,BRE和ERE,这是历史遗留的产物。egrep风格的正则表达式在
UNIX开发的早期就已经出现,但是Linux的创始人KenThompson觉得不需要在ed编辑器中使
用这样全方位的正则表达式支持,ed的标准后来演化为BRE。
ed又成为grep和sed的基础,故此。grep和sed支持的正则表达式类型是BRE。在pre-V7
时期,egrep被发明出来,egrep是使用的ERE风格正则。但是,当egrep, grep, fgrep合并成
个grep程序时,grep就同时支持不同风格的正则表达式〔通过一E选项支持ERE)o与此同时,egrep
虽然被从POSIX标准中踢出,但是许多UNIX/LINUX发行版本仍然文持egrep命令,而且许多历
史遗留脚本仍然在使用egrep,虽然标准做法应该是grep -E
使用ERE风格n则表达式的部分程序有egrep, awk和lex. lex是一个词法分析器构建程序,
除了特殊情况下,很少在shell编程中用到。
扩展
除了前面提到的BRE和ERE这两种标准正则表达式支持外,许多程序根据需求提供正则表
达式的语法扩展。最常见的扩展是\<和\>,分别匹配单词开头和单词结尾。
单词的开头有两种情况,一种是位于行的起始位置,一种是紧跟在非一单词组成字符后面;同样,单词的结尾也是两种情况;行的末尾和尾随一个非单词组成字符。
GUN支持额外的正则表达式运算符
|
含义
|
\w
|
匹配任何单词组成字符,等同[[:alnum:]]
|
\W
|
匹配任何非单组成字符,等同[^[:alnum:]]
|
\<\>
|
匹配单词的开头和结尾
|
\b
|
匹配单词开头和结尾处所找到的空字符o \bword就等同\<word\>
|
\B
|
匹配两个单词组成字符间的空字符串
|
\’\`
|
分别匹配emacs缓冲区的开头和结尾。GNU程序通常将它们视为与^和S同义
|
研究罗马数字
有点脑袋大,那天有心情在研究吧。
解析电话号码实例
echo '80055512121234' | grep -E"^[[:digit:]]{3}[^[:digit:]]*[[:digit:]]{3}[^[:digit:]]*[[:digit:]]{4}[^[:digit:]]*[[:digit:]]*$"
echo '800-555-1212' | grep -E"^[[:digit:]]{3}[^[:digit:]]*[[:digit:]]{3}[^[:digit:]]*[[:digit:]]{4}[^[:digit:]]*[[:digit:]]*$"
echo '800-555-1212-1234' | grep -E"^[[:digit:]]{3}[^[:digit:]]*[[:digit:]]{3}[^[:digit:]]*[[:digit:]]{4}[^[:digit:]]*[[:digit:]]*$"
echo 'work 1-(800) 555.1212 #1234' | grep-E "[[:digit:]]{3}[^[:digit:]]*[[:digit:]]{3}[^[:digit:]]*[[:digit:]]{4}[^[:digit:]]*[[:digit:]]*$"
表达式解析一下:
[[:digit:]]{3} 三位数字
[^[:digit:]]* 非数字的任何东西(或者没有)
[[:digit:]]{3} 三位数字
[^[:digit:]]* 非数字的任何东西(或者没有)
[[:digit:]]{4} 四位数字
[^[:digit:]]* 非数字的任何东西(或者没有)
[[:digit:]]* 数字(可没有)
分享到:
相关推荐
本文将基于《LINUX与UNIX SHELL编程指南》这本书的读书笔记,深入探讨Linux与Unix Shell编程的核心知识点。 一、Shell概述 Shell是一个命令解释器,它接收用户输入的命令并执行。在Linux和Unix系统中,常见的Shell...
一、正则表达式是什么? 正则表达式是用于描述字符排列和匹配模式的一种语法规则。它主要用于字符串的模式分割、匹配、查找及替换操作。 二、正则表达式与通配符 1. 正则表达式 用来在文件中匹配符合条件的字符...
8. **正则表达式**:在shell中,正则表达式是进行文本匹配和查找的强大工具。 9. **错误处理和调试**:学会如何处理脚本运行时的错误,以及如何调试脚本。 10. **权限与文件属性**:理解Linux的用户和组权限系统,...
Unix Shell 实例精解学习笔记 本文档主要介绍 Unix ... Unix Shell 实例精解学习笔记,涵盖了 Unix Shell 的基础知识、正则表达式的基础知识和应用等内容,为学习 Unix Shell 和正则表达式提供了有价值的参考资料。
本文主要探讨了在Shell脚本编程中如何运用`grep`、`sed`与`awk`结合正则表达式来实现一些具体的需求。这些工具在文本处理方面极其强大,通过灵活运用它们,可以高效地完成文本搜索、替换、格式化等任务。 #### 二、...
9. **正则表达式**: Shell脚本中常结合正则表达式进行文本匹配和替换,提高了数据处理的灵活性。 10. **Shell函数和别名**: 函数可以封装复杂逻辑,别名则可以为常用命令设置快捷方式,简化命令行操作。 11. **...
"shell编程笔记.zip_programy5v_shell_shell编程"这个压缩包包含了有关Shell编程的详细资料,特别是“shell编程笔记.pdf”文件,很可能是对这一主题的深入讲解。 首先,Shell编程的基础知识包括了解不同的Shell类型...
本文将详细解析Linux Shell编程中的几个关键概念:正则表达式、find命令、grep命令以及sed命令。 1. **正则表达式**: 正则表达式是一种强大的文本匹配模式,用于在文本中寻找符合特定规则的字符串。在Shell编程中...
《LINUX与UNIX SHELL编程指南》是一本深入探讨Linux和UNIX系统中Shell脚本编程技术的书籍。这本书旨在帮助读者理解和掌握Shell编程的核心概念,从而能够编写出高效、实用的自动化脚本,提高日常系统管理和任务执行的...
- 使用正则表达式 `/^[A-Z][a-z]*3[0-5]/` 查找以大写字母开头、接着零个或多个小写字母,然后是数字 3 和一个 0-5 之间的数字的行。 通过以上知识点的学习,读者可以更好地理解和掌握 Unix Shell 编程的基本概念...
6. **正则表达式**:在Shell编程中,正则表达式用于文本匹配和搜索,是进行文本处理的关键工具。 7. **脚本调试与错误处理**:学习如何追踪和调试脚本中的问题,以及如何有效地处理错误和异常。 8. **高级特性**:...
### Unix Shell 实例精解 — 学习...以上是对《Unix Shell 实例精解》学习笔记中涉及的关键知识点的总结,涵盖了Shell的基础概念、功能以及正则表达式的使用方法。这些知识点为深入理解Unix Shell提供了坚实的基础。
通过上述内容,我们不仅了解了 Unix Shell 的基本概念和功能,还深入学习了正则表达式的应用方法。这些知识点对于掌握 Unix 操作系统的核心技能至关重要,有助于提高日常工作效率和解决问题的能力。
通过阅读这本书和相关的读书笔记,读者不仅可以学习到基本的shell编程知识,还能深入理解Linux和Unix系统的工作原理,从而更好地管理和自动化日常工作。这本书对于系统管理员、开发者以及所有希望提高Linux终端技能...
此外,了解正则表达式也是Shell编程的关键。正则表达式是用于匹配字符串模式的工具,常用于文件名匹配、文本搜索和替换等场景。例如,`*`代表零个或多个任意字符,`?`代表单个任意字符,`[abc]`匹配a、b或c中的任意...
这份"Shell编程指南"不仅包含基础的Shell命令使用,还有作者的心得笔记,将理论与实践相结合,帮助读者更深入地理解和掌握Shell编程,提升日常的系统管理和自动化任务处理能力。通过学习,你可以编写出高效的自动化...
《LINUX与UNIX SHELL编程指南》是一本深入讲解Linux和...结合书中的实例和《LINUX与UNIX SHELL编程指南》读书笔记-二次发布版.pdf,学习效果会更佳,因为笔记通常会提炼关键概念并提供实践经验,有助于巩固理论知识。
《UNIX Shell 范例精解(第4版)》是一部深入探讨UNIX Shell编程的经典著作,旨在帮助读者理解和掌握Shell脚本的编写技巧。在UNIX和Linux系统中,Shell是用户与操作系统交互的重要接口,同时也是编写自动化任务和系统...
通过阅读《LINUX与UNIX SHELL编程指南》读书笔记.pdf,你可以深入理解这些概念并获取更多实际案例。而www.pudn.com.txt可能包含额外的资料链接或示例,帮助你扩展学习资源。 总的来说,学习Linux Shell编程需要理解...