正则表达式——边界

📅 2026/8/6 18:44:48
正则表达式——边界
边界1、行的起始与结束2、单词边界与非单词边界3、其他锚位符4、使用元字符的字面值5、添加标签5.1、使用sed添加标签5.2、使用Perl添加标签待匹配的文本THERIMEOFTHEANCYENTMARINERE,INSEVENPARTS.ARGUMENT.How a Ship having passed the Line was driven by Storms to the cold Country towards the South Pole;and how from thence she made her course to the tropical Latitudeofthe Great Pacific Ocean;andofthe strange things that befell;andinwhat manner the Ancyent Marinere came back to his own Country.I.It is an ancyent Marinere,And he stoppeth oneofthree:By thy long grey beard and thy glittering eye Now wherefore stoppest me?1、行的起始与结束就像之前看到的那样要匹配行或字符串的起始要使用脱字符U005E​^根据上下文^会匹配行或者字符串的起始位置有时还会匹配整个文档的起始位置。而上下文则依赖于应用程序和在应用程序中所使用的选项。如你所知若要匹配行或字符串的结尾位置要使用美元符$请确定RegExr中的multiline多行选项被勾选。global全局选项在打开RegExr时默认勾选但是本例中你可以勾选也可以不勾选该选项。如果不勾选multiline选项整个目标文本被视做一个字符串。在上方的文本框中键入下面这个正则表达式^How.*Country\.$它会匹配以单词How开头的整行。请注意结尾的点号之前有一个反斜杠它对点号进行转义这样点号就被解释为字面值。如果不对点号转义它就会匹配任意字符。如果想匹配作为字面值的点号则必须将点号转义或者将其放入字符组中。如果不勾选multiline选项会是什么情况高亮显示功能会被关闭。在不勾选multiline但选dotall的情况下键入^THE.*\?$可以看到它匹配了整个文本。dotall选项表示点号除了匹配其他字符之外还会匹配换行符。取消勾选dotall选项则该表达式什么也不匹配。而以下表达式^THE.*则匹配第一行。再点击dotall选项全部文本都会被匹配。不需要使用? $来匹配文本的结尾。2、单词边界与非单词边界我们已经多次遇到使用\b的情况了。它匹配单词边界。请尝试\bTHE\b在勾选global选项的情况下这个表达式会匹配第一行的两个THE。就像^和$一样\b是个零宽度断言表面上它会匹配空格或者是行起始而实际上它匹配的是个零宽度的不存在的东西。你有没有注意到第二个THE两边的空格是没有标亮的这是因为它们不是匹配的部分。这个理解起来不是很容易但你可以通过观察它匹配和不匹配的内容来理解。你还可以匹配非单词边界。非单词边界匹配除单词边界之外的位置比如单词或者字符串中的字母或数字。要匹配一个非单词边界试一下\Be\B看看它匹配了什么​。可以看到它匹配了小写字母e而匹配的字母e的两边都是其他字母或者是非单词字符。零宽度断言不会匹配两边的字符但它会识别文字e的两边是否是非单词边界。在有些应用程序中指定单词边界的另一种方法是使用\来指定单词的开头而使用\来指定单词结尾。这是比较旧的语法在很多最新的正则表达式应用程序中无法使用。但在有些情况下这种语法就很有用因为它不会像\b那样匹配任意单词边界而是允许你分别匹配单词的开头或结尾。如果你的系统上有vi或者vim可以用这类编辑器试一下。即使你没用过vim这也很简单只要按照以下步骤做即可。在命令行或者shell窗口中将路径改为诗文所在的地方再用这个命令打开vim rime.txt然后输入以下查找命令/\再按回车键Enter或返回键Return​。在vim中使用斜杠符/开始一次查找。请观察光标可以看到本次查找过程会找到单词的结尾。按下按键n可重复查找。再输入/\再按回车键Enter或返回键Return​。这次查找会找出单词的开头。要退出vim键入ZZ即可。这一语法也可用于grep。自从20世纪70年代grep像sed一样一直是Unix系统的主要工具。​20世纪80年代我一个同事的车牌上面就写着GREP。​在shell提示符中试试这个命令grep-Eoc\(THE|The|the)\rime2.txt-E选项表示要使用扩展的正则表达式ERE​而不是grep默认使用的基本正则表达式BRE​。-o选项代表结果只显示一行中与模式相匹配的那部分。-c选项的意思是只返回结果的数量。单引号中的模式会对THE、The或者the进行整词匹配。这就是和 帮你寻找的。这个命令返回的是259也就是找到的单词的数目。另一方面如果不使用和结果则不同。这样做grep-Eoc(THE|The|the)rime2.txt得到的数字就是327为什么因为该模式只匹配整词和任意包含该词的字符序列。这就是和能派上用场的一个原因。3、其他锚位符与锚位符^相似以下简写式匹配主题词的起始\A这个写法不是在所有的正则表达式程序中都可以使用的但可以在Perl和PCRE中使用。要匹配主题词的结尾可以使用\Z在某些上下文中还可用\zpcregrep是带有PCRE库的grep版本。​​安装之后要使用以上语法则这样写pcregrep-c\A\s(THE|The|the)rime2.txt单词the出现在行首附近位置且之前有一个或多个空格的次数为108次命令-c会返回这个次数。接下来输入命令pcregrep-n(MARINERE|Marinere)(.)? \Zrime.txt这一命令会匹配一行主题词尾部的MARINERE或Marinere之后是任何可选字符在本例中可选字符就是标点符号或者字母S。​点号两边的括号不是必需的。​可以看到输出为1:THERIMEOFTHEANCYENTMARINERE,10:It is an ancyent Marinere,38:The bright-eyed Marinere.63:The bright-eyed Marinere.105:God save thee,ancyent Marinere!282:Ifear thee,ancyent Marinere!702:He loves to talkwithMarinerespcregrep的-n选项在输出的每行起始处显示行号。pcregrep与grep的命令行选项十分相似。要了解所有选项输入pcre--help4、使用元字符的字面值可以用\Q和\E之间的字符集匹配字符串字面值。为了展示这一点在RegExr下方文本框中输入以下元字符.^$*?|(){}[]\-这15个元字符在正则表达式中有特殊含义用来编写匹配模式。​连字符在字符组的方括号中用来表示范围。但在其他情况下则无特殊含义。​如果你在RegExr上方的文本框中尝试匹配这些字符则不会看到任何结果。为什么呢因为RegExr会认为这是个正则表达式而不是字符串字面值。现在试一下\Q$\E它将匹配$因为\Q和\E之间的任意字符都会被解释为普通字符。​记住可以在元字符之前加一个\使其匹配字面值。​5、添加标签在RegExr中取消勾选global但勾选multiline点击Replace标签然后在第一个文本框中输入^(.*)$这会匹配第一行文本并将其捕捉。然后在下一个文本框标号为2中输入以下内容!DOCTYPEhtml\nhtmllangen\nheadtitleRime/title/head\nbody\nh1$1/h1输入替换文本的时候你会注意主题词文本在显示结果的文本框标号为4中变了包含了你刚刚添加的标记。RegExr很好地展示了添加标记的一种方式但它也有自己的局限性比如说它不能将结果保存为文件。因此我们不能把目光仅局限于浏览器。5.1、使用sed添加标签在RegExr中能完成的工作完全可以使用sed在命令行环境下做到。sed中的插入命令i允许你在文件或字符串中的某个位置之前插入文本。而与i命令相反的是命令a它在某个位置之后添加文本后面会用到a​。以下命令从第1行开始插入HTML5的doctype文档类型和其他标记sed 1i\!DOCTYPEhtml\html lang\en\\head\titleRime/title\/head\bodys/^/h1/s/$/\/h1/q rime.txt行尾的反斜杠\允许你在该流中插入新行而不会提前执行命令。引号前的反斜杠将引号转义为字面值。正确运行这个sed命令会得到如下输出!DOCTYPEhtmlhtml langenheadtitleThe Rimeofthe AncyentMariner(1798)/title/headbodyh1THERIMEOFTHEANCYENTMARINERE,INSEVENPARTS./h1以上sed命令保存在实例代码库中的top.sed文件中。用以下命令运行这些代码sed-ftop.sed rime2.txt可以得到与前面的命令相同的输出。要将输出保存到文件则可以把输出重定位到一个文件中比如sed-ftop.sed rime2.txttemp除了会在屏幕上显示结果重定位的那部分temp还会将输出保存到文件temp中。5.2、使用Perl添加标签下面尝试用Perl完成同样的工作。先不解释试一试这个perl-neprint ! DOCTYPE html\ html lang\en\\ headtitleRime/title/head\ body\ if $. 1; s/^/h1/; s/$/\/h1/m; print; exit; rime2.txt以下是该命令的工作过程。变量 $表示当前行使用if语句测试。如果if语句返回true真​则当前行就是第1行。当Perl用if语句找到第1行时它会打印文档类型doctype和几个HTML标签。和在sed中一样这里也需要将引号转义。第一个替换操作在行起始位置插入标签第二个替换操作在行尾处插入标签。第二个替换操作结尾处的m表示使用多行修饰符。这就保证了该命令会识别第一行的结尾。如果没有m则$会匹配该文件的结尾。命令print打印替换结果。命令exit则会立即结束Perl程序。否则因为有-n选项它会循环执行文件的每一行但这里不需要。以上命令要键入很多内容。我将这些Perl代码放入名为top.pl的文件中也可以在代码库中找到。#! /usr/bin/perl -nif($1){print! DOCTYPE html\ html lang\en\\ head\ titleThe Rime of the Ancyent Mariner (1798)/title\ /head\ body\ ;s/^/h1/;s/$/\/h1/m;print;exit;}使用合集运行这个文件perl top.pl rime2.txt得到的结果与前面是一样的只是形式上稍有不同。​就像在sed中一样你可以用将输出重定位到文件中。​