正则表达式详解<一>

正则表达式是一种处理字符串的微型语言;有以下的基本术语:

l  模式(pattern):正则表达式实际上是通过字符串表达的一个模式

l  匹配(match): 判断正则表达式和给出的序列[first , last),是否全部匹配

l  搜索(search):判断在给定的序列里是否存在和正则表达式匹配的子字符串

l  替换(replace):将匹配到的子字符串替换成其他的字符串

在C++里边默认的语法是ECMAScript,这是最强大的正则表达式的语法;

1.  ECMAScript语法

1.   锚点(anchor)

特殊字符^和$是锚点,分别匹配到字符串的开头和结尾。例如:^text$,表达的意思就是只匹配text字符串

     2.通配符(wildcard)

     可以用来匹配除了换行符以外的任何字符,例如:正则表达式是:a.b,可以匹配到abc,adb,

但是不可是:acdb

3.替换

A|B 可以匹配到A或则是B

4.分组(捕获组)

例如:(.)(ab|cd)(.)其中有三个标记的子表达式,例如输入1ab5则可以捕获到,1 。 ab。5这仨个捕获组。

     5.重复

     * 表示匹配零次或则多次之前的部分。例如:a*b 可以匹配到b , ab , aab , aaab

     + 表示匹配一次以及一次以上之前的部分,例如:a+b可以匹配到ab , aab但是不能是b

     ? 表示匹配到零次或是一次以前的部分,例如: a ? b 可以匹配到ab , b 但是不能位 aab

     {…}表示区间重复,a{n}表示匹配到的a刚好位n个,a{n,}表示匹配到的a为n位或则n位以上;a{n,m}表示匹配到的a的个数位>=n和<=m个;

     6.贪婪匹配和非贪婪匹配

     输入字符串位: aaabbb

     贪婪匹配:正则表达式:(a+)(ab)*(b+) ,匹配到:”aaa””””bbb”

     非贪婪匹配:正则表达式:(a+?)(ab)*(b+)匹配到:“aa“”ab””bb”;

     7.优先级

     第一:元素本身

     第二:量词:+,* , ? {…}

     第三:串联:例如ab+c在量词之后绑定

     第四:替代符| ,最后绑定

     例如:正则表达式:ab+c|d,会匹配到abc, abbc , d , 如果添加括号,ab+(c|d)则匹配到

     , abc , abbc , abd abbd

     8,字符集合匹配

     [a-z]表示可以匹配到a到z之间的任意一个字符,(注意是任意一个,而不是多个)

     [a-zA-Z]表示可以匹配到a到z以及A到Z之间对的任意一个字符;

     另一种方法是使用某种字符类,表示方法[:name:]例如:

     [[:digit:]]表示可以匹配到0~9之间的任意一个数字;

     这里的name可以是以下:

    

Name

Expression

digit

数字

d

和digit一样

xdigit

数字和表示16进制的abcdef或则ABCDEF

alpha

字母字符所有的大小写

alnum

Alpha和digit的组合

w

和alnum一样

lower

小写字母

upper

大写字母

blank

一行文本中分割单词的空格符

punct

标点符号字符,包括不是alnum意外的所有图形字符

应用:

问题:表示0~9的任意一个以及多个数字的匹配

解答:(1)[0-9]+

          (2)  [[:digit:]]+

          (3)  [[:d:]]+

          (4)  \d+

问题:匹配除了小写字母以外的任意字符

解答:(1) [[:upper:]]

         (2) [^[:lower:]]

 

     9.后向引用

     \n  n是>0的整数,表示第n个捕捉组,例如:

     正则表达式:([:d:]*)-.*-\1

     可以匹配到:123-abc-123 , 789-kdf-789 , 9-m-9

     但是不可是:123-abc-1234,必须是123,和第一个捕获组一样的内容;

     10.C++里的转义   

     转移\d,在C++里应该将其转移,因为\是特殊字符在C++里,所以需要转移,转义位:

     \\d.

     转移\,这个更加麻烦。应该转译为:\\\\

     例如:
     正则表达式:( |\\n|\\r|\\\\)

     搜索空格 , 换行符 , 回车符 , 反斜杠;

转载于:https://www.cnblogs.com/boost/p/10425492.html

<think> 我们正在讨论正则表达式中的两个特殊构造:`?<=`(正向后行断言)和`?=`(正向先行断言),它们都属于零宽断言(lookaround assertions),用于匹配某些位置,而不消耗字符。 引用说明:我们参考了引用[1]和[3]中关于正则表达式的基础知识和元字符说明。 以下是对这两个断言结构的详细解释: ### 1. 正向先行断言(Positive Lookahead)`(?=...)` - **功能**:匹配个位置,该位置后面的内容必须匹配`...`表达式,但不消耗字符(即匹配结果中不包含`...`的内容)。 - **示例**:要匹配后面跟着百分号的数字,可以使用`\d+(?=%)`。在字符串`100% and 200 dollars`中,它会匹配到`100`(因为后面有%),而不会匹配`200`(因为后面是空格和dollars)。 - **语法**:`(?=pattern)` - **图示**: ``` 文本: "100% 200" 正则: \d+(?=%) 匹配结果: "100"(注意:只匹配数字,不包含%) ``` ### 2. 正向后行断言(Positive Lookbehind)`(?<=...)` - **功能**:匹配个位置,该位置前面的内容必须匹配`...`表达式,同样不消耗字符。 - **示例**:要匹配前面有`$`符号的数字,可以使用`(?<=\$)\d+`。在字符串`Price: $100 and $200`中,它会匹配到`100`和`200`(因为前面有$),而不会匹配其他数字。 - **语法**:`(?<=pattern)` - **注意**:在Java中,后行断言中的模式必须是固定长度的(即不能使用`*`、`+`等不确定长度的量词)。例如,`(?<=\$\d*\.)`是非法的,因为`\d*`长度不定;但`(?<=\$\d{1,3}\.)`是允许的,因为长度范围固定(1到3位数字)。引用[2]中提到,不同语言对命名的支持不同,但这里我们只关注断言。 - **图示**: ``` 文本: "$100 and $200" 正则: (?<=\$)\d+ 匹配结果: "100" 和 "200"(不包含$) ``` ### 共同特 1. **零宽度**:它们只匹配位置,不消耗字符,所以匹配到的内容不会包含断言中的模式。 2. **非捕获**:它们不会捕获匹配的文本,仅作为条件判断。 3. **方向**: - 先行断言(Lookahead):向右(文本后方)检查。 - 后行断言(Lookbehind):向左(文本前方)检查。 ### 对比示例 假设我们有字符串`apple pie, apple juice, apple`,我们想匹配后面有`pie`的`apple`: - 正则:`apple(?= pie)` → 匹配第个`apple`(后面是` pie`),不匹配其他。 假设我们想匹配前面有`juice`的`apple`(注意:因为前面有`juice`的`apple`实际上是`apple`后面没有空格,但这里我们调整下): 实际上,这个例子中,如果字符串是`juice apple`,我们可以用`(?<=juice )apple`来匹配`apple`。 ### 进阶:负向断言 除了正向断言,还有负向断言(即要求不匹配): - 负向先行断言:`(?!...)`,例如`apple(?! pie)`匹配后面不是`pie`的`apple`(如`apple juice`中的`apple`)。 - 负向后行断言:`(?<!...)`,例如`(?<!juice )apple`匹配前面不是`juice `的`apple`。 ### 总结 - `?=` 和 `?<=` 是正则表达式中强大的定位工具,用于设置条件而不占用字符。 - 使用场景:提取特定上下文中的内容,避免匹配到不需要的部分。 下面是个Java代码示例,展示这两个断言的使用: ```java import java.util.regex.*; public class LookaroundExample { public static void main(String[] args) { String text = "$100 and 200% and €300"; // 匹配前面有$的数字 Pattern patternBehind = Pattern.compile("(?<=\\$)\\d+"); Matcher matcherBehind = patternBehind.matcher(text); while (matcherBehind.find()) { System.out.println("后行断言匹配: " + matcherBehind.group()); // 100 } // 匹配后面有%的数字 Pattern patternAhead = Pattern.compile("\\d+(?=%)"); Matcher matcherAhead = patternAhead.matcher(text); while (matcherAhead.find()) { System.out.println("先行断言匹配: " + matcherAhead.group()); // 200 } } } ``` 输出: ``` 后行断言匹配: 100 先行断言匹配: 200 ``` 希望以上解释能够帮助你理解这两个断言结构。正则表达式的断言功能在处理复杂文本时非常有用,尤其是需要精确上下文匹配的场景。 §§相关问题§§ 1. 正则表达式中的负向先行断言和负向后行断言如何使用? 2. Java正则表达式对后行断言的长度限制具体是什么? 3. 除了Java,Python和JavaScript中的正则断言有哪些差异? 4. 如何结合使用先行断言和后行断言来匹配特定格式的文本? 5. 在日志分析中,零宽断言有哪些实际应用案例? </think> ### 正则表达式 `?<=` 和 `?=` 详解正则表达式中,`?<=`(正向后行断言)和 `?=`(正向先行断言)属于**零宽断言**(lookaround assertions)。它们用于匹配特定位置而非实际内容,不消耗字符,仅作为匹配条件存在[^1][^3]。 --- #### 1. 正向先行断言 `(?=...)` **功能**:匹配右侧必须满足条件的位置 **特**: - 匹配位置,不消耗字符 - 右侧必须包含指定模式 - 语法:`pattern(?=condition)` **示例分析**: 文本:"`apple price: $5, orange price: $3`" 正则:`\d+(?=\$)` - `\d+`:匹配数字 - `(?=\$)`:要求数字右侧必须有 `$` **匹配结果**:`5` 和 `3`(不包含 `$`) **应用场景**: 提取价格数字:`"总价: ¥100"` → `\d+(?=¥)` 匹配 `100` --- #### 2. 正向后行断言 `(?<=...)` **功能**:匹配左侧必须满足条件的位置 **特**: - 匹配位置,不消耗字符 - 左侧必须包含指定模式 - 语法:`(?<=condition)pattern` **示例分析**: 文本:"`ID: A123, ID: B456`" 正则:`(?<=ID: )[A-Z]\d+` - `[A-Z]\d+`:匹配大写字母+数字 - `(?<=ID: )`:要求左侧必须有 `ID:␣` **匹配结果**:`A123` 和 `B456` **应用场景**: 提取特定前缀后的内容:`"电话: 13800138000"` → `(?<=电话: )\d{11}` 匹配 `13800138000` --- ### 核心对比 | 特性 | `?=` (先行断言) | `?<=` (后行断言) | |---------------|------------------------|------------------------| | **匹配方向** | 向右检查(后侧条件) | 向左检查(前侧条件) | | **消耗字符** | 否(零宽度) | 否(零宽度) | | **典型用途** | 后缀条件匹配 | 前缀条件匹配 | | **Java支持** | 完全支持 | 完全支持 | --- ### 组合使用案例 提取 `{}` 中的内容(不包含花括号): 文本:`"data={value: 42}, info={count: 100}"` 正则:`(?<=\{)[^{}]*(?=\})` - `(?<=\{)`:左侧必须有 `{` - `[^{}]*` :匹配非花括号内容 - `(?=\})` :右侧必须有 `}` **匹配结果**:`value: 42` 和 `count: 100` --- ### 注意事项 1. **性能影响**:复杂断言可能增加回溯开销[^1] 2. **长度限制**:Java后行断言模式需定长(如 `(?<=\d{3})` 有效,`(?<=\d+)` 无效) 3. **浏览器差异**:JavaScript 不支持后行断言中的变长模式(如 `(?<=a*)`) > 零宽断言通过位置条件实现精准匹配,是处理复杂文本解析的核心技术之[^3]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值