正则表达式——嵌入条件 📅 2026/8/5 14:41:28 嵌入条件1、为什么要嵌入条件2、正则表达式里的条件2.1、回溯引用条件2.2、前后查找条件1、为什么要嵌入条件123456-7890和123-456-7890都是可接受的北美电话号码格式而1234567890、123-456-7890和123-456-7890虽然都包含着数目正确的数字字符但它们的格式都不对。如果让你来编写一个正则表达式并让它只匹配可接受的格式不匹配其他格式你会怎么做这个问题看似简单其实颇有难度。下面是最容易想到的解决方案文本123-456-7890(123)456-7890(123)-456-7890(123-456-789012345678901234567890正则表达式\(?\d{3})?-?\d{3}-\d{4}结果\匹配一个可选的左括号——请注意这里必须对进行转义\d{3}匹配前三位数字\匹配一个可选的右括号-匹配一个可选的连字符\d{3}-\d{4}匹配剩余的七位数字中间用一个连字符分隔。原始文本中的最后两行不与这个模式匹配但第3行和第4行与之匹配——这是不正确的第3行的后面多了一个-第4行少了一个配对的右括号。把\? -替换为[\]-]可以排除第3行字符或-只能出现一个不允许两个同时出现但第4行还是无法排除。正确的模式应该只在电话代码里有一个左括号的时候才去匹配。更准确地说应该是如果电话号码里有一个左括号我们的模式必须去匹配如果不是这样它就必须去匹配-。这种模式如果不使用条件处理根本无法编写。2、正则表达式里的条件正则表达式里的条件要用来定义。事实上你们已经见过几种非常特定的条件了?匹配前一个字符或表达式——如果它存在的话。?和?匹配前面或后面的文本——如果它存在的话。嵌入条件语法也使用了这并没有什么让人感到吃惊的地方——因为嵌入条件不外乎以下两种情况根据一个回溯引用来进行条件处理。根据一个前后查找来进行条件处理。2.1、回溯引用条件回溯引用条件只在一个前面的子表达式搜索取得成功的情况下才允许使用一个表达式。听起来很费解我们还是用一个例子来说明好了你需要把一段文本里的IMG标签全都找出来不仅如此如果某个IMG标签是一个链接被括在A和/A标签之间的话你还要把整个链接标签匹配出来。请看下面这个例子文本!-- Nav bar --TDAHREF/homeIMGSRC/images/home.gif/AIMGSRC/images/spacer.figAHREF/searchIMGSRC/images/search.gif/AIMGSRC/images/spacer.gifAHREF/helpIMGSRC/images/help.gif/A/TD正则表达式([Aa]\s[^]\s*)?[Ii][Mm][Gg]\s[^](?(1)\s*\/[Aa])结果这个模式不解释是不容易看明白的。[Aa]\s[^]\s*将匹配一个A或a标签以及A或a标签的任意属性这个标签可有可无因为这个子表达式的最后有一个。接下来[Ii][Mm][Gg]\s[^]匹配一个IMG大小写均可及其任意属性。?1\s*/[Aa]是一个回溯引用条件——?1的含义是如果第一个回溯引用具体到本例就是A标签存在则使用\s*/[Aa]继续进行匹配换句话说只有当前面的A标签匹配成功才继续进行后面的匹配。如果1存在\s*/[Aa]将匹配结束标签/A之后出现的任意空白字符。注意 1检查第一个回溯引用是否存在。在条件里回溯引用编号本例中的1不需要被转义。因此?1是正确的?\1不正确但后者通常也能工作。这个语法提供了电话号码问题的解决方案如下所示文本123-456-7890(123)456-7890(123)-456-7890(123-456-789012345678901234567890正则表达式(\()?\d{3}(?(1)\)|-)\d{3}-\d{4}结果从结果看这个模式解决了问题但它是如何解决问题的呢和前面一样\ 也匹配一个可选的左括号但我们这次把它用括号括起来得到了一个子表达式。随后的\d{3}匹配一位数字的区号。?1\|-是一个回溯引用条件它将根据条件是否得到满足而去匹配或-——如果1存在也就是找到了一个左括号, \必须被匹配否则-必须被匹配。这样一来只有配对出现的括号才会被匹配如果没有使用括号或括号不配对电话号码中的区号和其余数字之间的-分隔符必须被匹配。提示 嵌入了条件的模式看上去往往非常复杂而这往往意味着调试工作会变得非常困难。如果别无选择先对整个模式的各组成部分分别进行调试再把它们拼装到一起这通常是一种比较好的办法。2.2、前后查找条件前后查找条件只在一个向前查找或向后查找操作取得成功的情况下才允许一个表达式被使用。定义一个前后查找条件的语法与定义一个回溯引用条件的语法大同小异——只需把回溯引用括号里的回溯引用编号替换为一个完整的前后查找表达式就行了。作为一个例子请你思考一下怎样匹配美国的邮政编码简称ZIP编码。美国邮政编码有两种格式一种是12345形式的ZIP格式另一种是12345-6789形式的ZIP4格式。只有ZIP4格式才必须使用连字符来分隔前5位和后4位数字。下面是一种解决方法文本111112222233333-44444-4444正则表达式\d{5}(-\d{4})?结果\d{5}匹配前5位数字-\d{4}匹配一个连字符和后4位数字它们必须一起出现或一起不出现。现在请考虑这样一个问题如果你不想匹配那些格式不正确的ZIP编码你该怎么办比如说在上面这个例子里在第3行原始文本的末尾有一个不应该出现在那里的连字符但这个号码还是出现在了最终的匹配结果里。怎样才能让这个格式不正确的ZIP编码不出现在最终的匹配结果里呢下面是用一个前后查找条件来解决这个问题的方法虽然这个问题并非只有这一种解决办法。正则表达式\d{5}(?(?-)-\d{4})结果分析\d{5}匹配前5位数字。接下来是一个?? --\d{4}形式的向前查找条件。这个条件使用了-来匹配但不消费一个连字符如果条件得到满足那个连字符存在, -\d{4}将匹配那个连字符和随后的4位数字。这样一来33333-将被排除在最终的匹配结果之外它有一个连字符所以满足给定条件但那个连字符的后面没有必须出现在那里的4位数字。