正则表达式学习笔记(一)正则表达式入门
正则表达式入门
作为编程语言的正则表达式
以语言做类比
完整的正则表达式由两种字符组成:特殊字符(special characters,例如文件名例子中的*)称为元字符(metacharacters)其他为‘文字’(literal),或者普通文本字符(normal text characters)。
为了便于理解可以把正则表达式想象为普通的语言,普通字符对应语言中的单词,而元字符对应语法。
Egrep元字符
行的起始和结束
脱字符‘^’:代表一行的开始。
美元符号‘$’:代表一行的结束。
这两元字符特别之处在于匹配的不是字符而是文本位置。
要养成按字符来理解正则表达式的习惯,例如:
不要这样:‘^cat’匹配以cat开头的行
而应该这样理解:‘^cat’匹配的是以c作为一行的第一个字符,紧接着一个a,紧接着一个t的文本。
字符组
匹配若干字符之一
如果我们需要搜索的单词是'grey',但又不确定该单词是否写作‘gray’,就可以使用正则表达式结构体‘[....]’。它允许使用这列出在某处期望匹配的字符,通常被称作字符组(character class)。
如[ea]匹配'e'或者‘a’。请注意,在字符组以外,普通字符都有‘接下来是’的意思,字符组内部的情况则完全不同,它是‘或’的意思。
在字符组内部,字符组元字符‘-’表示一个范围:例如‘[0-9a-z]’匹配数字和小写字母。请注意‘-’只有在字符组内部并且在字符普通字符中间时才是元字符。
排除型字符组
[^....]匹配任何一个未被列出的字符,注意不是‘不要匹配列出的字符’。如‘[^1-6]’匹配一个1到6以外的一个字符。
用点号匹配任意字符
元字符'.',是用来匹配任意字符的字符组的简便写法。
某些可能造成错误的情况:‘34[.-!]’中的‘.’不是元字符,而是普通字符,注意此时的‘-’是用来表示范围的,不是普通字符。
多选结构
‘|’是一个非常简洁的元字符,它的意思是‘或’。依靠它,我们可以把不同的子表达式组合成一个总的表达式,而这个总表达式又能够匹配任意的子表达式。子表达式被称为多选分支。
例如‘tom|price’,匹配tom或者price。我们可以把'gr[ea]y'写成‘grey|gray’或者‘gr(e|a)y’。注意后者用括号来限定多选结构的范围。多选结构可以包含多个字符,但不能超越括号的范围。
注意:一个字符组只能匹配目标文本中的单个字符,而每个多选结构自身都可能是完整的正则表达式,都可以匹配任意长度的文本。字符组可以算是一门独立的微型语言(例如对于元字符它们有自己的规定),而多选结构是正则表达式主体的一部分。
在一个包含多选结构的表达式中使用脱字符和美元符号要特别小心。区别‘^From|Subject|Date’和‘^(From|Subject|Date)’!
单词分界符
某些版本的egrep支持‘/<’和‘/>’来匹配单词的开始和结尾。它们被称作元字符序列(即由两个字符构成一个元字符)。
可选项元素
元字符‘?’代表一个可选项。把它加在一个字符后面,就表示此处允许出现此字符,不过它的出现并非匹配成功的必要条件。如,‘colu?or’。该元字符与之前介绍的元字符不同的地方在于,它只
作用于之前紧邻的元素。如‘July? (fourth | 4(th)?/)’
其他量词:重复出现
元字符‘+’:之前紧邻的元素出现一个或者多次(至少匹配一次)。
元字符‘*’:之前紧邻的元素出现多次,或者不出现。
‘?’‘+’‘*’统称量词。
注意:一个字符组就是一个元素,可以对它直接使用量词而不需要括号。
规定重复出现次数的范围:区间
某些版本的egrep可以使用元字符序列来自定义重现次数的区间。‘{min, max}’
括号及反向引用
前面介绍的括号的两种用途:1.限制多选项的范围。 2.将若干字符组合为一个单元,受量词的作用。
在许多流派的正则表达式中,括号能够记住它们所包含的子表达式匹配的文本。这种特性被叫做反向引用,它允许我们匹配表达式先前部分匹配的同样的文本。
如,‘([0-9])(a-z)/1/2’,其中‘/1’代表‘[0-9]’匹配的内容,‘/2’代表‘[a-z]’匹配的内容。
如,查找重复的单词: egrep -i '\<(a-z+) + \1\>'
神奇的转意符
‘\’,注意在字符组内部转意符无效。
环视
环视结构不匹配任何字符,只匹配文本中的特定位置(环视不占用任何字符)。例如,使用'(?= Jeffrey)Jeff' 得到比'Jeff'更精准的结果。
思考:'(?= Jeffrey)Jeff'和'Jeff(?=rey)'结果是一样的
顺序环视:从左到右查看文本,尝试匹配子表达式,如果能匹配,就返回匹配成功的信息。肯定型顺序环视用'(?=......)'表示。例如,'(?=\d)',表示如果
当前位置右边是数字则匹配成功。
逆序环视:从右向左查看文本。用'(?<=....)'表示,例如'(?<=\d)'表示如果当前位置左边有一个数字,则匹配成功。
环视例子:例如要把所有'Jeffs'换成'Jeff's'
以前的做法:
s/\b(Jerff)(s)\b/$1'$2/g
使用环视:
s/\bJeff(?=s\b)/Jeff'/g
s/(?<=\bJeff)(?=s\b)/'/g. 匹配位置加入撇号
否定环视:匹配成功的条件是子表达式无法匹配。
否定逆序环视: (?<!......)
否定顺序环视:(?!.....)
其他:
1.非捕获型括号:(?: ......)
2.匹配所有空白: \s
3.匹配所以非空白:\S
4.匹配[a-zA-Z0-9]: \w
5.匹配[^a-zA-Z0-9]:\W
6.匹配[0-9]: \d
7.匹配[^0-9]: \D