首页 > 代码库 > 正则表达式(grep,egrep,fgrep)

正则表达式(grep,egrep,fgrep)



1.正则表达式概述

正则表达式又称正规表示式、正规表示法、正规表达式、规则表达式、常规表示法(英语:Regular Expression,在代码中常简写为regexregexpRE),计算机科学的一个概念。正则表达式使用单个字符串来描述、匹配一系列符合某个句法规则的字符串。在很多文本编辑器里,正则表达式通常被用来检索、替换那些符合某个模式的文本。

许多程序设计语言都支持利用正则表达式进行字符串操作。正则表达式这个概念最初是由Unix中的工具软件(例如sedgrep)普及开的。正则表达式通常缩写成“regex”,单数有regexpregex,复数有regexpsregexesregexen


2.基本语法

    一个正则表达式通常被称为一个模式(pattern),为用来描述或者匹配一系列符合某个句法规则的字符串。例如:HandelHndelHaendel这三个字符串,都可以由“H(a||ae)ndel”这个模式来描述。大部分正则表达式的形式都有如下的结构:

选择

|竖直分隔符代表选择。例如“gray|grey”可以匹配greygray

数量限定

某个字符后的数量限定符用来限定前面这个字符允许出现的个数。最常见的数量限定符包括“+”、“?”和“*”(不加数量限定则代表出现一次且仅出现一次):

+加号代表前面的字符必须至少出现一次。(1次、或多次)。例如,“goo+gle”可以匹配googlegoooglegoooogle;

?问号代表前面的字符最多只可以出现一次。(0次、或1次)。例如,“colou?r”可以匹配color或者colour;

*星号代表前面的字符可以不出现,也可以出现一次或者多次。(0次、或1次、或多次)。例如,“0*42”可以匹配42042004200042等。

匹配

圆括号可以用来定义操作符的范围和优先度。例如,“gr(a|e)y”等价于“gray|grey”,“(grand)?father”匹配fathergrandfather

上述这些构造子都可以自由组合,因此,“H(ae?|)ndel”和“H(a|ae|)ndel”是相同的。

精确的语法可能因不同的工具或程序而异。

 

3.正则表达式基础

基本概念

3.1.字符串组成

对于字符串“a5”,是由两个字符“a”、“5”以及三个位置组成的,这一点对于正则表达式的匹配原理理解很重要。

            wKioL1RnTiuzR0aXAAA3MNshD7c746.jpg


3.2.占有字符和零宽度

正则表达式匹配过程中,如果子表达式匹配到的是字符内容,而非位置,并被保存到最终的匹配结果中,那么就认为这个子表达式是占有字符的;如果子表达式匹配的仅仅是位置,或者匹配的内容并不保存到最终的匹配结果中,那么就认为这个子表达式是零宽度的。

占有字符还是零宽度,是针对匹配的内容是否保存到最终的匹配结果中而言的。

占有字符是互斥的,零宽度是非互斥的。也就是一个字符,同一时间只能由一个子表达式匹配,而一个位置,却可以同时由多个零宽度的子表达式匹配。

由一类字符书写的模式,其中有些字符不表示字符字面意义,而是表达控制或通配的功能。

 

3.3.正则表达式构成

正则表达式由两种字符构成。一种是在正则表达式中具体特殊意义的“元字符”,另一种是普通的“文本字符”。

元字符可以是一个字符,如“^”,也可以是一个字符序列,如“\w”。

   我们建立一个文件来说明元字符。

#cat test.txt
ab
cb
abx
aaaaaab
aaaaaaaaaaaaaab

                                    

 

元字符(Meta Character

1.[] 字符组(CharacterClasses)

字符组可以匹配[ ]中包含的任意一个字符。虽然可以是任意一个,但只能是一个。

字符组支持由连字符“-”来表示一个范围。当“-”前后构成范围时,要求前面字符的码位小于后面字符的码位。

[^] 排除型字符组。排除型字符组表示任意一个未列出的字符,同样只能是一个。排除型字符组同样支持由连字符“-”来表示一个范围。

         字符匹配:字符通配

         .:匹配任意单个字符。

         wKiom1RnTn_Rp7g5AAAomnZ5mCA249.jpg

         []:匹配指定集合中的任意单个字符。

         wKiom1RnTpPQqsW_AAAnujMptpw616.jpg

         [^]:匹配指定集合外的任意单个字符

         wKioL1RnTx-QtIdGAAAna4_Q5x0980.jpg

        

2.量词(Quantifier

 量词表示一个子表达式可以匹配的次数。量词可以用来修饰一个字符、字符组,或是用()括起来的子表达式。一些常用的量词被定义成独立的元字符。

       *:表达式匹配前面任意次,0,1或者多次,前面字符出现与否都匹配,相当于{0,}

         wKioL1RnT0eDQe9pAAAtH3eOhk4676.jpg

 

 \+:表达式匹配1次或意多次,至少1次,相当于{1,}

     wKiom1RnTvug_4crAAAlXhEw4k8295.jpg

 

\?:表达式匹配0次或1次,相当于{0,1}

     wKioL1RnT3yhOXWyAAAvBnQaKAg880.jpg

 

\{m\}:表达式匹配其前面的字符m

     wKiom1RnTxyCfELkAAApFTxoBKA845.jpg

 

\{m,n\}:表达式匹配最少m次,最多n

     wKioL1RnT6LDlpnGAAAul5zJI1I115.jpg

         注意:在不是动态生成的正则表达式中,不要出现“{1}”这样的量词,如“\w{1}”在结果上等价于“\w”,但是会降低匹配效率和可读性,属于画蛇添足的做法。

         .*:匹配任意长度的任意字符

         wKioL1RnT8rD6YUxAAAp79LSNM0841.jpg

 

3.位置锚定

         ^:行首锚定,出现最左侧

         wKioL1RnT-GyXbWuAAAV7nj3kVo244.jpg

        

     $:行尾锚定,出现最右侧

         wKioL1RnUAbQbbm-AAAbFsE9-dM551.jpg

        

         ^$:表示空白行

         wKiom1RnT6ngV2b1AAASf_tIVCU573.jpg

        

         \<:词首锚定,在查找的单词模式的左侧;\<char

         wKioL1RnUCyA6CYAAAAbHGVVLHk174.jpg

        

         \>:词尾锚定,在查找的单词模式的右侧;char\>

         wKioL1RnUDzxzXI5AAAkvsSJjOc442.jpg

         \<pattern\>:匹配单词

         wKiom1RnT9_BY_LuAAAZgk_KUco462.jpg

 

4.捕获组(Capture Group

捕获组就是把正则表达式中子表达式匹配的内容,保存到内存中以数字编号或手动命名的组里,以供后面引用。

(Expression):普通捕获组,将子表达式Expression匹配的内容保存到以数字编号的组里

(?<name> Expression):命名捕获组,将子表达式Expression匹配的内容保存到以name命名的组里

普通捕获组(在不产生歧义的情况下,简称捕获组)是以数字进行编号的,编号规则是以“(”从左到右出现的顺序,从1开始进行编号。通常情况下,编号为0的组表示整个表达式匹配的内容。

命名捕获组可以通过捕获组名,而不是序号对捕获内容进行引用,提供了更便捷的引用方式,不用关注捕获组的序号,也不用担心表达式部分变更会导致引用错误的捕获组。

 

非捕获组:一些表达式中,不得不使用( ),但又不需要保存( )中子表达式匹配的内容,这时可以用非捕获组来抵消使用( )带来的副作用。

(?:Expression):进行子表达式Expression的匹配,并将匹配内容保存到最终的整个表达式的区配结果中,但Expression匹配的内容不单独保存到一个组内

 

反向引用:捕获组匹配的内容,可以在正则表达式的外部程序中进行引用,也可以在表达式中进行引用,表达式中引用的方式就是反向引用。

反向引用通常用来查找重复的子串,或是限定某一子串成对出现。

\1\2:对序号为12的捕获组的反向引用

\k<name>:对命名为name的捕获组的反向引用

    举例:

(a|b)\1”在匹配“abaa”时,匹配成功,匹配到的结果是“aa”。“(a|b)”在尝试匹配时,虽然既可以匹配“a”,也可以匹配“b”,但是在进行反向引用时,对应()中匹配的内容已经是固定的了。

我们来实验一下:

# cat test2.txt
acbhelloacb123
aabhiacb123
abaworldabb123
acbbadacb234
adbcloseadb234
adbcloseasb2345

wKiom1RnT_rib9Q2AAB9WPWCg0c859.jpg

wKioL1RnUICT64auAABvMy0mAmc382.jpg


贪婪与懒惰

当正则表达式中包含能接受重复的限定符时,通常的行为是(在使整个表达式能得到匹配的前提下)匹配尽可能多的字符。以这个表达式为例:a.*b,它将会匹配最长的以a开始,以b结束的字符串。如果用它来搜索aabab的话,它会匹配整个字符串aabab。这被称为贪婪匹配。

有时,我们更需要懒惰匹配,也就是匹配尽可能少的字符。前面给出的限定符都可以被转化为懒惰匹配模式,只要在它后面加上一个问号?。这样.*?就意味着匹配任意数量的重复,但是在能使整个匹配成功的前提下使用最少的重复。现在看看懒惰版的例子吧:

a.*?b匹配最短的,以a开始,以b结束的字符串。如果把它应用于aabab的话,它会匹配aab(第一到第三个字符)和ab(第四到第五个字符)。

懒惰限定符

*?        重复任意次,但尽可能少重复

+?        重复1次或更多次,但尽可能少重复

??         重复0次或1次,但尽可能少重复

{n,m}?     重复nm次,但尽可能少重复

{n,}?    重复n次以上,但尽可能少重复


5.grep,egrep,fgrep介绍

Unixgrep家族包括grepegrepfgrepegrepfgrep的命令只跟grep有很小不同。egrepgrep的扩展,支持更多的re元字符, fgrep就是fixed grepfast grep,它们把所有的字母都看作单词,也就是说,正则表达式中的元字符表示回其自身的字面意义,不再特殊。linux使用GNU版本的grep。它功能更强,可以通过-G-E-F命令行选项来使用egrepfgrep的功能

 

Linux grep是基础的正则表达式,命令用于在文件内查找指定的字符串。

grep (globalsearch regular expression(RE) and print out the line,全面搜索正则表达式并把行打印出来)是一种强大的文本搜索工具,它能使用正则表达式搜索文本,并把匹配的行打印出来。

         grep[-acinv] [--color=auto] ‘搜寻字符串‘ filename

选项与参数:

-a :将 binary 文件以 text 文件的方式搜寻数据

-c :计算找到搜寻字符串的次数

-i :忽略大小写的不同,所以大小写视为相同

-n :顺便输出行号

-v :反向选择,亦即显示出没有搜寻字符串内容的那一行!

--color=auto :可以将找到的关键词部分加上颜色的显示喔!

 

grepGlobal searchRegular expression and Print out the line

egrepExtended Globalsearch Regular expression and Print out the line

fgrepFast Global searchRegular expression and Print out the line

 

Linux egrep是扩展的正则表达式,命令用于在文件内查找指定的字符串。

egrep执行效果与"grep-E"相似,使用的语法及参数可参照grep指令,与grep的不同点在于解读字符串的方法。

egrep是用extendedregular expression语法来解读的,而grep则用basic regular expression 语法解读,extended regularexpressionbasic regular expression的表达更规范。

 

扩展正则表达式的元字符:和基础的没啥区别,就是有些字符不需要\

 

字符匹配

 .:匹配任意单个字符

[]:指定集合中的任意单个字符

[^]:匹配指定集合外的任意单个字符

+       匹配前面的字符出现至少1

 

匹配次数限定

*:匹配前面任意次,01或者多次,前面字符出现与否都匹配

?:匹配其前面的字符0次或1

{m}:匹配其前面的字符m

{m,n}:匹配其前面的字符至少m次,至多n{m,}   {0,n}

.*:匹配任意长度的任意字符

 

字符锚定

^:行首锚定,出现最左侧

$:行尾锚定,出现最右侧

^$:表示空白行

\<:词首锚定,在查找的单词模式的左侧;\<char

\>:词尾锚定,在查找的单词模式的右侧;char\>

\<pattern\>:匹配单词

 

捕获组的反向引用 和grep差不多

(a.b).*\1 模式从左到右,引用第#个左括号以及与其匹配右括号之间的模式匹配到的内容,\1 , \2

a|b  a或者bab|cd就是ab或者cd

 

Linuxfgrep不使用正则表达式,查询速度比grep命令快,但是不够灵活:它只能找固定的文本,而不是规则表达式。

如果你想在一个文件或者输出中找到包含星号字符的行

    wKioL1RnTHTC1pptAABiPVZ2KFk533.jpg

    wKiom1RnTAOQOKqGAABhey5yZtU879.jpg



本文出自 “龙之守护” 博客,谢绝转载!

正则表达式(grep,egrep,fgrep)