`
searun
  • 浏览: 176685 次
  • 性别: Icon_minigender_1
  • 来自: 合肥
社区版块
存档分类
最新评论

[跟我学正则表达式] 6. 位置匹配

阅读更多

 

你现在已经学习到了如何在文本中的任意位置匹配各种字符及其组合以及任意的次数。尽管如此,有时候需要在特定的位置匹配文本。这就是将在本章要介绍的位置匹配。

 

使用边界

边界处理表示在特定的位置指定匹配文本。为了理解位置匹配的需求,考虑下面的例子:

文本

The cat scattered his food all over the room.

正则表达式
cat

结果
The cat scat tered his food all over the room.
分析

此模式将匹配所有出现过的 cat ,即使此单词是出现在“scattered”中。事实上,这并不是我们所需要的。如果你将所有出现过的 cat 都变为 dog ,则将会出现下面的结果:
The dog sdogtered his food all over the room.

这使得我们需要边界匹配,也就是说使用特殊的元字符在模式中指定边界。

 

使用单词边界

第一个边界,也是最常用的是通过使用“ \b ”指定字符边界。就像其名字所描述的那样,“ \b ”用来匹配单词的开始和结束。

为了演示“ \b ”的用法,下面是前一个例子并使用了指定的边界:

文本
The cat scattered his food all over the room.

正则表达式
\bcat\b

结果
The cat scattered his food all over the room.

分析

单词 cat 的前面和后面都有一个空格。所以可以匹配“\bcat\b”(空格是一种用来分隔单词的字符)。而在scattered中的 cat 则不会被匹配,因为 cat 单词的前后分别是 s t (不能匹配 \b )。

 

注意:到底“ \b ”是匹配什么呢?实际上正则表达式引擎并不懂得英语,或者任何的其他语言,所以也并不知道字符边界。“ \b ”只是匹配“ \w ”(文字数字式字符和下划线)和“ \W ”之间的位置。

需要注意的是如果匹配整个单词,需要在单词的前后都是用“ \b ”。考虑下面的例子:

文本
The captain wore his cap and cape proudly as
he sat listening to the recap of how his
crew saved the men from a capsized vessel.

正则表达式
\bcap

结果
The cap tain wore his cap and cap e proudly as
he sat listening to the recap of how his
crew saved the men from a cap sized vessel.

分析

模式“ \bcap ”匹配了任何以“ cap ”开始的单词,所以匹配了四个单词,其中三个并不是单词 cap 。下面是一个相同的例子,但是使用了后置“ \b ”:

文本
The captain wore his cap and cape proudly as
he sat listening to the recap of how his
crew saved the men from a capsized vessel.

正则表达式
cat\b

结果
The captain wore his cap and cape proudly as
he sat listening to the recap of how his
crew saved the men from a capsized vessel.

分析

cap\b ”匹配使用 cap 结束的任意单词,所以找到了两个匹配,包括一个不是 cap 的单词。

 

如果需要匹配指定的单词,正确的模式是使用“\bcap\b”。

笔记:“ \b ”并不是匹配一个字符;实际上是匹配一个位置。所有模式“ \bcat\b ”实际上将匹配三个字符“ cat ”,而不是五个字符的长度。

为了指定不在单词边界匹配,可以使用“ \B ”。下面的例子使用了“ \B ”元字符来定位两边是空格的元字符。

文本
Please enter the nine-digit id as it
appears on your color - coded pass-key.

正则表达式
\B-\B

结果
Please enter the nine-digit id as it
appears on your color - coded pass-key.

分析

模式“\B-\B”匹配了含有断字符的连字符。所以“nine-digit”和“pass-key”字符中的“ - ”不能匹配,而“color - coded”则可以。就像在第四章中看到的一样,大写的元字符和小写的元字符的功能是相反的。

 

注意:有些正则表达式实现支持另外两个元字符。“ \b ”匹配单词的开始和结束,“\<”匹配一个单词的开始,“ \> ”则匹配一个单词的结束。尽管这些元字符提供了额外的控制,但是对于这些的支持是有限的(在 egrep 是支持的,但是大部分实现中并不支持)。

 

定义字符串边界

字符边界用于单词位置的匹配(单次的开始,单词的结束,整个单词等)。字符串边界用来匹配整个字符串的开始和结束。字符串边界匹配的元字符是“ ^ ”和“ $ ”,分别用于字符串的开始和接受。

注意:在第三章中,你已经学习到了“ ^ ”可以用于对字符集的否定。但是它又如何来指示一个字符串的开始呢?

^ ”是几个有几种用途的元字符中的一个。如果位于集合开始处的话,则表示否定;如果在集合外面,则将匹配字符串的开始位置。

为了演示字符串边界的用法,看看下面的例子。合法的 XML 文档开始于<?xml>并且有部分额外属性(可能是版本号,如<xml version="1.0" ?>)。下面是一个检测是否为合法 XML 文档的方法:

文本
<?xml version="1.0" encoding="UTF-8" ?>
<wsdl:definitions targetNamespace="http://tips.cf "
xmlns:impl="http://tips.cf" xmlns:intf="http://tips.cf"
xmlns:apachesoap="http://xml.apache.org/xml-soap"

正则表达式
<\?xml.*\?>

结果
<?xml version="1.0" encoding="UTF-8" ?>
<wsdl:definitions targetNamespace="http://tips.cf "
xmlns:impl="http://tips.cf" xmlns:intf="http://tips.cf"
xmlns:apachesoap="http://xml.apache.org/xml-soap"

分析

此模式看起来可以工作。<\?xml可以匹配<?xml,“ .* ”匹配任何字符(零个或者一个“ . ”实例),\?> 则匹配?>。但实际上这并不是一个准确的测试。看看下面的例子,使用同样的模式匹配文本:

文本
This is bad, real bad!
<?xml version="1.0" encoding="UTF-8" ?>
<wsdl:definitions targetNamespace="http://tips.cf "
xmlns:impl="http://tips.cf" xmlns:intf="http://tips.cf"
xmlns:apachesoap="http://xml.apache.org/xml-soap"

正则表达式
<\?xml.*\?>

结果
This is bad, real bad!
<?xml version="1.0" encoding="UTF-8" ?>
<wsdl:definitions targetNamespace="http://tips.cf "
xmlns:impl="http://tips.cf" xmlns:intf="http://tips.cf"
xmlns:apachesoap="http://xml.apache.org/xml-soap"

分析

模式“<\?xml.*\?> ”匹配了第二行文本。尽管这个 XML 标签可以在第二行中找到,但是这个例子却是非法的(对这个 XML 文档的处理将会出现问题)。

 

这里的需求是需要保证 XML 标签是出现在字符串的开始位置,而这正是“ ^ ”元字符所能够做的:

文本
<?xml version="1.0" encoding="UTF-8" ?>
<wsdl:definitions targetNamespace="http://tips.cf "
xmlns:impl="http://tips.cf" xmlns:intf="http://tips.cf"
xmlns:apachesoap="http://xml.apache.org/xml-soap"

正则表达式
^\s*<\?xml.*\?>

结果
<?xml version="1.0" encoding="UTF-8" ?>
<wsdl:definitions targetNamespace="http://tips.cf "
xmlns:impl="http://tips.cf" xmlns:intf="http://tips.cf"
xmlns:apachesoap="http://xml.apache.org/xml-soap"

分析

^ ”匹配了字符串的开始位置。“^\s*”因此可以匹配文本的开始位置,后跟着可选的空格字符(在合法的 XML 文档中可以包括空格、制表符和换行等)。完整的“^\s*<\?xml.*\?>”匹配了开始的 XML 标签并正确处理了空格字符。

 

提示:模式“^\s*<\?xml.*\?>”可以工作,但是只有这里的 XML 例子是不完整的。对于一个完整的 XML 例子,你可能会发现贪婪的匹配可用。也就是说,有些时候可以使用“.*?”而不是“.*”。

$ ”用法是一样的。下面的模式可以用来检查在 Web 页面的</html>标签之后没有其他内容。
</[Hh][Tt][Mm][Ll]>\s*$
H, T, M, 和L每个字符都使用了集合,可以用来处理各种不同的大小写组合,同时\s*$可以匹配字符串后的所有空白字符。

注意:模式“^.*$”是一个语法上正确的正则表达式,此模式总是可以找到一个匹配,所以其实也是无用的。你能知道此模式匹配什么,什么时候不能找到一个匹配吗?

 

使用多行模式

“^”匹配字符串的开始,“ $ ”匹配字符串的结束。但这是一般情况,有一个例外,或者说,有一种方法可以改变这种行为。

许多的正则表达式实现都支持使用特殊的元字符来改变其他元字符的行为,其中一个是“ (?m) ”,可以启用多行模式。在多行模式下,正则表达式引擎将换行符作为字符串的分隔符,所以“^”将匹配文本的开始或者一行的开始,而“ $ ”则可以匹配文本的结束或者是一行的结尾处。

如果使用多行模式的话,(?m)必须放置在模式的开始处,就像下面的例子一样。这个例子的正则表达式用来在代码中定位 JavaScript 注释:

文本
<SCRIPT>
function doSpellCheck(form, field) {
   // Make sure not empty
   if (field.value == '') {
      return false;
   }
   // Init
   var windowName='spellWindow';
   var spellCheckURL='spell.cfm?formname=comment&fieldname='+field.name;
...
   // Done
   return false;
}
</SCRIPT>

正则表达式
(?m)^\s*//.*$

结果
<SCRIPT>
function doSpellCheck(form, field) {
   // Make sure not empty
   if (field.value == '') {
      return false;
   }
   // Init
   var windowName='spellWindow';
   var spellCheckURL='spell.cfm?formname=comment&fieldname='+field. name;  
   // Done
   return false;
}
</SCRIPT>

分析

“^\s*//.*$”将匹配字符串的开始,任意空格后接“ // ”(定义了 JavaScript 的注释),然后是任何文本,最后是文本的结束。但是这个模式只对最开始的第一个注释起作用(并且需要是唯一的文本)。“ (?m) ”修饰符“(?m)^\s*//.*$”将换行符也作为字符串的分隔符,所以所有的注释都将被匹配。

 

注意:“(?m)”在大部分的正则表达式实现中并不支持。

笔记:有些正则表达式实现还支持使用“ \A ”匹配字符串的开始,“ \Z ”匹配字符串的结束。如果支持的话,则这些元字符的功能和“ ^ ”“ $ ”是一样的。但是和“ ^ ”“ $ ”不同的是,这些元字符不能使用(?m)修饰,所以也不能用于多行模式。

 

小结

正则表达式可以匹配文本和字符串的指定位置。“ \b ”用来指定字符边界(“ \B ”刚好相反)。“ ^ ”和“ $ ”标记了字符串边界,分别匹配字符串的开始和结束。当使用(?m)修饰符的时候,还可以匹配一行的开始和结尾。

 

@ 亦歌亦行 http://searun.iteye.com

分享到:
评论

相关推荐

    精通正则表达式(第3版).pdf

    2. 模式的匹配:正则表达式可以匹配简单的字符序列,也可以匹配复杂的字符组合,包括单个字符、字符集、字符序列、可选字符、重复字符等。 3. 字符集和选择:字符集用方括号表示,用于匹配方括号内的任意一个字符,...

    shell正则表达式.zip

    10. **模式修饰符**:在正则表达式末尾可以添加模式修饰符来改变匹配行为,如`i`忽略大小写,`g`全局匹配,`m`使`^`和`$`匹配每一行的开始和结束。 在实际使用中,结合这些知识点,我们可以编写出强大的shell命令,...

    正则表达式常用例子总结

    以下是我整理的一些正则表达式的常用例子,旨在帮助理解其基本用法和功能。 1. **基本匹配** - 匹配单个字符:`\d` 代表数字,`\w` 代表字母或数字,`\s` 代表空白符。 - 匹配范围:`[a-z]` 匹配小写字母,`[A-Z]...

    正则表达式

    目前,正则表达式已经在很多软件中得到广泛的应用,包括*nix(Linux, Unix等),HP等操作系统,PHP,C#,Java等开发环境,以及很多的应用软件中,都可以看到正则表达式的影子。  正则表达式的使用,可以通过简单...

    Python爬虫 Re库与正则表达式的细节解析

    Python爬虫(二十三) 学习Python爬虫过程中的心得体会以及知识点的整理,方便我自己查找,也希望可以和大家一起交流。 —— Re库与正则表达式的细节解析 —— ...例如使用正则表达式匹配字符串 ‘\section’。因为反

    regex_debug-html.rar_DEMO

    在IT行业中,正则表达式(Regular Expression,简称regex)是一种强大的文本处理工具,用于匹配、查找、替换或提取字符串中的特定模式。本项目“regex_debug-html.rar_DEMO”是一个JavaScript实现的正则表达式验证的...

    Java正则相关的Pattern和Matcher类及遇到的坑

    此篇文章是记录我在学习Java正则表达式时候学到的和遇到的坑。 先来说说 Matcher 里面的三个方法(取的结果以group()方法为例子) matches():整个匹配,只有整个字符序列完全匹配成功,才返回True,否则返回False...

    高级Bash脚本编程指南--中文版(advance_bash_scriipt_progaming_guide).pd苹果脚本跟我学.pdff

    ]]`条件测试支持正则表达式匹配,可以进行复杂的文本模式查找。 8. **错误处理**:通过`set -e`,脚本会在遇到错误时立即退出,确保脚本的健壮性。 9. **环境变量**:如`PATH`、`HOME`等,它们提供了系统级的信息...

    你必须知道的495个C语言问题(PDF)

    3.10 如果我不使用表达式的值, 我应该用++i 或i++ 来自增一个变量 吗? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15 3.11 为什么如下的代码int a = 100, b = 100; long int c = a * b;...

    跟我学写Makefile

    ### 跟我学写Makefile #### 概述与目的 本文档旨在通过系统而详尽的方式指导读者学习如何编写Makefile。Makefile是一种用于自动化构建过程的脚本文件,广泛应用于软件开发中,特别是在大型项目的编译过程中。通过...

    python爬取wb图跟视频

    - **正则表达式 (re)**: 用于匹配和提取网页中的特定模式,如URL或特定文本。 - **Selenium**: 当网页内容由JavaScript动态加载时,需要使用自动化浏览器工具如Selenium模拟用户交互。 - **User-Agent管理**: 更改...

    使用Matlab下载googlefinance上面的option数据版本2012a-getoption.m

    这个东西是叫做matlab正则表达式的应用,想系统学的同学可以上网搜,比我讲的要好, 我只是要用的时候拿出来看, 上图:   大家看到strike的规律没有? 都是strike 后面跟着一个价格, 所以,下面这个code就是讲得是...

    万能makefile写法详解,一步一步写一个实用的makefile

    该命令表示把源串内的match都替换成replace,s指示match可以是正则表达式。 g表示把每行内所有match都替换,如果去掉g,则只有每行的第1处match被替换(实际上不需要g,因为一个.d文件中,只会在开头有一个main.o:)。...

    C语言FAQ 常见问题列表

    o 7.7 有人跟我讲, 数组不过是常指针。 o 7.8 我遇到一些 ``搞笑" 的代码, 包含 5["abcdef"] 这样的 ``表达式"。 这为什么是合法的 C 表达式呢 ? o 7.9 既然数组引用会蜕化为指针, 如果 arr 是数组, 那么 arr 和...

    你必须知道的495个C语言问题

    6.9 有人跟我讲,数组不过是常指针。这样讲准确吗? 6.10 我还是很困惑。到底指针是一种数组,还是数组是一种指针? 6.11 我看到一些“搞笑”的代码,包含5["abcdef"]这样的“表达式”。这为什么是合法的C语言...

Global site tag (gtag.js) - Google Analytics