正则表达式 环视问题

hoszone 2008-06-19 08:53:02
String te1 ="shoma s 12345678";
String reg2 ="(?=(\\d\\d\\d)+$)";

System.out.println("reg2:"+te1.replaceFirst(reg2, ","));

输出:reg2:shoma s 12,345678

结果为什么是12,345678 而不是12345,678
主要是不太明白$符号,它是怎么处理的.

String reg22 ="(?<=(\\d\\d\\d)+$)";
System.out.println("reg22:"+te1.replaceFirst(reg22, ","));
为什么输出:
reg22:shoma s 12345678,

thanks....
...全文
424 19 打赏 收藏 转发到动态 举报
写回复
用AI写文章
19 条回复
切换为时间正序
请发表友善的回复…
发表回复
安卓机器人 2011-02-23
  • 打赏
  • 举报
回复
看我分析的正确不:
String te1 ="shoma s 12345678";
String reg2 ="(?=(\\d\\d\\d)+$)";

System.out.println("reg2:"+te1.replaceFirst(reg2, ","));

如果按照匹配应该是这样:
showma s 123 456 78
然后3被","替换,6被“,”替换,但是环视只是消耗位置,不占字符,所以就成了这样
showma s 12,345,678 被替换的字符要往后推,总之是这样理解的,不知道对不对

输出:reg2:shoma s 12,345678

结果为什么是12,345678 而不是12345,678
主要是不太明白$符号,它是怎么处理的.

String reg22 ="(?<=(\\d\\d\\d)+$)";
System.out.println("reg22:"+te1.replaceFirst(reg22, ","));
为什么输出:
reg22:shoma s 12345678,

thanks....

这个是逆序环视,那么他的第一个位置应该在最后,所以逗号也在最后面
qiandongbo 2008-06-19
  • 打赏
  • 举报
回复
谢谢火龙果~前2天才学的正则,很多还没完全弄明白,来的太好了~
  • 打赏
  • 举报
回复
[Quote=引用 2 楼 jingulang 的回复:]
借楼顺便问问

"^[\\s&&[^\\n]]*$" 怎么解释 这是匹配代码空行的正则

我没读懂
[/Quote]

^[\\s&&[^\\n]]*$

\\s 表示:[ \t\n\x0B\f\r],而 [^\\n] 表示非 \n 的所有字符,&& 表示并集

[\\s&&[^\\n]] 表示的是除去 \n 之外 \\s 中还剩下的字符串,那就是 [ \t\x0B\f\r]

^[\\s&&[^\\n]]* 表示在开头和结尾处匹配非 \n 的空白字符(或者说啥都没有),我们就
可以认为这是个空行。

表达式必须加上多行标志,以使 ^ $ 表示行首和行尾,不加的话表示开头和结尾,表达式应改成:
(?m)^[\\s&&[^\\n]]*$

或者在使用 Pattern 编译加上标志:
Pattern pattern = Pattern.compile("^[\\s&&[^\\n]]*$", Pattern.MULTILINE);


=========================================================================================

[Quote=引用 15 楼 qiandongbo 的回复:]
粗粗的问下?=是什么意思啊,我那个没看明白
[/Quote]

(?=) 表示字符缝隙后得有什么字符,比如:表达式 a(?=b) 能匹配 ab 但不能匹配 ac,
因为限定 a 的后面只能是 b,而 (?=b) 表示 ab 之间的缝隙。
hoszone 2008-06-19
  • 打赏
  • 举报
回复
明白了,谢谢,火龙果 ......
qiandongbo 2008-06-19
  • 打赏
  • 举报
回复
粗粗的问下?=是什么意思啊,我那个没看明白
jingulang 2008-06-19
  • 打赏
  • 举报
回复
楼上讲的明白~楼上讲的明白~
  • 打赏
  • 举报
回复
正则表达式的匹配是从左边开始的啊,当然先匹配到 2 和 3 之间了。

abc 12345678 的匹配过程如下:

(?=(\\d\\d\\d)+$) 以下简称 A

(\\d\\d\\d)+$ 以下简称 B

1:一个一个地移,直到移到 1 的前面的缝隙(因为后面是数字了),这时环视后面的字符串 12345678(因为 A 的环视
结构带有 $ 因此需要环视后面所有的字符串),可以看到 12345678 并不能与 B 进行匹配(因为需要数字的个数是
3 的倍数),这时匹配指示器往后移。
2:移到 1 和 2 之间,再环视后面的字符串 2345678 这时也不能与 B 进行匹配,这时匹配指示器再往后移。
3:移到 2 和 3 之间,再环视后面的字符串 345678 这时很好,能与 B 进行匹配了,使用替换在 2 和 3 之间插入逗号,
完成后匹配指示器再往后移。
4:移到 3 和 4 之间,再环视后面的字符串 45678 这时也不能与 B 进行匹配,这时匹配指示器再往后移。
4:移到 4 和 5 之间,再环视后面的字符串 5678 这时也不能与 B 进行匹配,这时匹配指示器再往后移。
5:移到 5 和 6 之间,再环视后面的字符串 678 能与 B 进行匹配了,使用替换在 5 和 6 之间插入逗号,完成后匹配指示
器再往后移。
6:继续如上步骤,直到匹配指示器指向 8 的后面,这时没有字符了,匹配完成。
hoszone 2008-06-19
  • 打赏
  • 举报
回复
bao110908

我正在看呢本书,感谢你的解释,我因为不太明白,所以把它拆分了来请教大家
hoszone 2008-06-19
  • 打赏
  • 举报
回复
恩,我明白你的意思,全部的时候是12,345,678
但是我就是不太明白为什么他第一次的是在2和3之间,而不是在5和6之间
或者说他是怎么匹配的,过程是什么?

感谢你的回复.....
  • 打赏
  • 举报
回复
$ 在未指定 Pattern.MULTILINE 参数或者 (?m) 内嵌表达式时,表示的是输入字符串的结尾。
如果指定了 Pattern.MULTILINE 参数或者 (?m) 时,表示的是输入字符串中每一行的结尾。

另:^ 与 $ 类似,表示开头或者是行首。

跟楼上所说的那样,你采用的是 replaceFirst,这个只能替换一个,并不能替换所有的。

另外,你的这个表达式还有一点点问题:

1,当字符串为“shoma s 123456789”时,会被换成“shoma s ,123,456,789”,这应该不会是想要的结果;
2,当字符串为“shoma s 123456789 abc”时,采用这个表达式不能进行匹配。

改进一下后的代码:

import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class Test {

public static void main(String[] args) {
String[] strs ={
"shoma s 1",
"shoma s 12",
"shoma s 123",
"shoma s 1234",
"shoma s 12345",
"shoma s 123456",
"shoma s 1234567",
"shoma s 12345678",
"shoma s 123456789",
"shoma s 1234567890",
"shoma s 1 aa",
"shoma s 12 aa",
"shoma s 123 aa",
"shoma s 1234 aa",
"shoma s 12345 aa",
"shoma s 123456 aa",
"shoma s 1234567 aa",
"shoma s 12345678 aa",
"shoma s 123456789 aa",
"shoma s 1234567890 aa",
"shoma s 1aa",
"shoma s 12aa",
"shoma s 123aa",
"shoma s 1234aa",
"shoma s 12345aa",
"shoma s 123456aa",
"shoma s 1234567aa",
"shoma s 12345678aa",
"shoma s 123456789aa",
"shoma s 1234567890aa",
"123 1234 abc 12345 5 aa 123456 1234567 12345678aa"
};
String regex ="(?<=\\d)(?=(\\d\\d\\d)+(?!\\d))";
// 多个字符串采用如下方式替换,可以节省正则表达式编译的时间
Pattern pattern = Pattern.compile(regex);
Matcher matcher = pattern.matcher("");
for(int i = 0; i < strs.length; i++) {
String str = matcher.reset(strs[i]).replaceAll(",");
System.out.println(str);
}
// 单个字符串采用如下方式替换
// str = str.replaceAll(regex, ",");
}
}
anqini 2008-06-19
  • 打赏
  • 举报
回复
[Quote=引用 6 楼 ssh000 的回复:]
anqini
=========
String reg2 ="(?=(\\d\\d\\d)+$)";

不太明白第一次匹配为什么在2和3之间,为什么不在5和6之间呢
[/Quote]
你用的是replaceFirst,只把第一个匹配的换掉!而不是全部的,你换成replaceAll看看,就知道了
jingulang 2008-06-19
  • 打赏
  • 举报
回复
另外楼主的那个正则

(\\d\\d\\d)+ 代表 3个数字 出现1次或多次 是不是三个数三个数的匹配

jingulang 2008-06-19
  • 打赏
  • 举报
回复
[Quote=引用 4 楼 anqini 的回复:]
引用 2 楼 jingulang 的回复:
借楼顺便问问

"^[\\s&&[^\\n]]*$" 怎么解释 这是匹配代码空行的正则

我没读懂

就是,\\s并且不是换行符,这样的0次或者多次!
\\s:空白字符:[ \t\n\x0B\f\r]
[/Quote]


主要是没明白^和$符号,以XXX开头和以XXX结尾,它是怎么断句的

是匹配以(\\s并不是\\n)零次或多次 开头
还是匹配以 (\\s并不是\\n)零次或多次 结尾?


另外没明白换行符属于啥 没概念啊
hoszone 2008-06-19
  • 打赏
  • 举报
回复
anqini
=========
String reg2 ="(?=(\\d\\d\\d)+$)";

不太明白第一次匹配为什么在2和3之间,为什么不在5和6之间呢
amethystic 2008-06-19
  • 打赏
  • 举报
回复
这个是正向预查。它不消耗字符,和$,^一样只匹配一个位置,所以在这里它就匹配了2和3中间的那个位置,所以结果就是在2和3中间加入了一个逗号。
anqini 2008-06-19
  • 打赏
  • 举报
回复
[Quote=引用 2 楼 jingulang 的回复:]
借楼顺便问问

"^[\\s&&[^\\n]]*$" 怎么解释 这是匹配代码空行的正则

我没读懂
[/Quote]
就是,\\s并且不是换行符,这样的0次或者多次!
\\s:空白字符:[ \t\n\x0B\f\r]
anqini 2008-06-19
  • 打赏
  • 举报
回复
[Quote=引用楼主 ssh000 的帖子:]
String te1 ="shoma s 12345678";
String reg2 ="(?=(\\d\\d\\d)+$)";

System.out.println("reg2:"+te1.replaceFirst(reg2, ","));

输出:reg2:shoma s 12,345678

结果为什么是12,345678 而不是12345,678
主要是不太明白$符号,它是怎么处理的.

String reg22 ="(? <=(\\d\\d\\d)+$)";
System.out.println("reg22:"+te1.replaceFirst(reg22, ","));
为什么输出:
reg22:shoma s 12345678,

thanks....
[/Quote]
第一:因为你换的是第一个匹配,replaceFirst
因为你匹配的是(\\d\\d\\d)+$,后面允许出现这种格式的,12 345 678,因为2和3之间的index满足第一个匹配这个匹配器~!所以这样的,假如你换用replaceAll,就能看出来了

第二:你的匹配其找的是前面允许出现的格式,因为前面有shoma s 这些英文字母,所以不匹配,更不能replaceFirst了!
jingulang 2008-06-19
  • 打赏
  • 举报
回复
借楼顺便问问

"^[\\s&&[^\\n]]*$" 怎么解释 这是匹配代码空行的正则

我没读懂
精通正则表达式第三版 搜集于网络 前言..........I 第1章:正则表达式入门.... 1 解决实际问题... 2 作为编程语言的正则表达式... 4 以文件名做类比... 4 以语言做类比... 5 正则表达式的知识框架... 6 对于有部分经验的读者... 6 检索文本文件:Egrep. 6 Egrep元字符... 8 行的起始和结束... 8 字符组... 9 用点号匹配任意字符... 11 多选结构... 13 忽略大小写... 14 单词分界符... 15 小结... 16 可选项元素... 17 其他量词:重复出现... 18 括号及反向引用... 20 神奇的转义... 22 基础知识拓展... 23 语言的差异... 23 正则表达式的目标... 23 更多的例子... 23 正则表达式术语汇总... 27 改进现状... 30 总结... 32 一家之言... 33 第2章:入门示例拓展.... 35 关于这些例子... 36 Perl简短入门... 37 使用正则表达式匹配文本... 38 向更实用的程序前进... 40 成功匹配的副作用... 40 错综复杂的正则表达式... 43 暂停片刻... 49 使用正则表达式修改文本... 50 例子:公函生成程序... 50 举例:修整股票价格... 51 自动的编辑操作... 53 处理邮件的小工具... 53 用环视功能为数值添加逗号... 59 Text-to-HTML转换... 67 回到单词重复问题... 77 第3章:正则表达式的特性和流派概览.... 83 在正则的世界中漫步... 85 正则表达式的起源... 85 最初印象... 91 正则表达式的注意事项和处理方式... 93 集成式处理... 94 程序式处理和面向对象式处理... 95 查找和替换... 98 其他语言中的查找和替换... 100 注意事项和处理方式:小结... 101 字符串,字符编码和匹配模式... 101 作为正则表达式的字符串... 101 字符编码... 105 正则模式和匹配模式... 110 常用的元字符和特性... 113 字符表示法... 115 字符组及相关结构... 118 锚点及其他“零长度断言” 129 注释和模式量词... 135 分组,捕获,条件判断和控制... 137 高级话题引导... 142 第4章:表达式的匹配原理.... 143 发动引擎... 143 两类引擎... 144 新的标准... 144 正则引擎的分类... 145 几句题外话... 146 测试引擎的类型... 146 匹配的基础... 147 关于范例... 147 规则1:优先选择最左端的匹配结果... 148 引擎的构造... 149 规则2:标准量词是匹配优先的... 151 表达式主导与文本主导... 153 NFA引擎:表达式主导... 153 DFA引擎:文本主导... 155 第一想法:比较NFA与DFA.. 156 回溯... 157 真实世界中的例子:面包屑... 158 回溯的两个要点... 159 备用状态... 159 回溯与匹配优先... 162 关于匹配优先和回溯的更多内容... 163 匹配优先的问题... 164 多字符“引文” 165 使用忽略优先量词... 166 匹配优先和忽略优先都期望获得匹配... 167 匹配优先、忽略优先和回溯的要旨... 168 占有优先量词和固化分组... 169 占有优先量词,?+、*+、++和{m,n}+. 172 环视的回溯... 173 多选结构也是匹配优先的吗... 174 发掘有序多选结构的价值... 175 NFA、DFA和POSIX.. 177 最左最长规则... 177 POSIX和最左最长规则... 178 速度和效率... 179 小结:NFA与DFA的比较... 180 总结... 183 第5章:正则表达式实用技巧.... 185 正则表达式的平衡法则... 186 若干简单的例子... 186 匹配连续行(续前)... 186 匹配IP地址... 187 处理文件名... 190 匹配对称的括号... 193 防备不期望的匹配... 194 匹配分隔符之内的文本... 196 了解数据,做出假设... 198 去除文本首尾的空白字符... 199 HTML相关范例... 200 匹配HTML Tag. 200 匹配HTML Link. 201 检查HTTP URL. 203 验证主机名... 203 在真实世界中提取URL. 206 扩展的例子... 208 保持数据的协调性... 209 解析CSV文件... 213 第6章:打造高效正则表达式.... 221 典型示例... 222 稍加修改——先迈最好使的腿... 223 效率vs准确性... 223 继续前进——限制匹配优先的作用范围... 225 实测... 226 全面考查回溯... 228 POSIX NFA需要更多处理... 229 无法匹配时必须进行的工作... 230 看清楚一点... 231 多选结构的代价可能很高... 231 性能测试... 232 理解测量对象... 234 PHP测试... 234 Java测试... 235 VB.NET测试... 237 Ruby测试... 238 Python测试... 238 Tcl测试... 239 常见优化措施... 240 有得必有失... 240 优化各有不同... 241 正则表达式的应用原理... 241 应用之前的优化措施... 242 通过传动装置进行优化... 246 优化正则表达式本身... 247 提高表达式速度的诀窍... 252 常识性优化... 254 将文字文本独立出来... 255 将锚点独立出来... 256 忽略优先还是匹配优先?具体情况具体分析... 256 拆分正则表达式... 257 模拟开头字符识别... 258 使用固化分组和占有优先量词... 259 主导引擎的匹配... 260 消除循环... 261 方法1:依据经验构建正则表达式... 262 真正的“消除循环”解法... 264 方法2:自顶向下的视角... 266 方法3:匹配主机名... 267 观察... 268 使用固化分组和占有优先量词... 268 简单的消除循环的例子... 270 消除C语言注释匹配的循环... 272 流畅运转的表达式... 277 引导匹配的工具... 277 引导良好的正则表达式速度很快... 279 完工... 281 总结:开动你的大脑... 281 第7章:Perl 283 作为语言组件的正则表达式... 285 Perl的长处... 286 Perl的短处... 286 Perl的正则流派... 286 正则运算符和正则文字... 288 正则文字的解析方式... 292 正则修饰符... 292 正则表达式相关的Perl教义... 293 表达式应用场合... 294 动态作用域及正则匹配效应... 295 匹配修改的特殊变量... 299 qr/…/运算符与regex对象... 303 构建和使用regex对象... 303 探究regex对象... 305 用regex对象提高效率... 306 Match运算符... 306 Match的正则运算元... 307 指定目标运算元... 308 Match运算符的不同用途... 309 迭代匹配:Scalar Context,不使用/g. 312 Match运算符与环境的关系... 316 Substitution运算符... 318 运算元replacement 319 /e修饰符... 319 应用场合与返回值... 321 Split运算符... 321 Split基础知识... 322 返回空元素... 324 Split中的特殊Regex运算元... 325 Split中带捕获型括号的match运算元... 326 巧用Perl的专有特性... 326 用动态正则表达式结构匹配嵌套结构... 328 使用内嵌代码结构... 331 在内嵌代码结构中使用local函数... 335 关于内嵌代码和my变量的忠告... 338 使用内嵌代码匹配嵌套结构... 340 正则文字重载... 341 正则文字重载的问题... 344 模拟命名捕获... 344 效率... 347 办法不只一种... 348 表达式编译、/o修饰符、qr/···/和效率... 348 理解“原文”副本... 355 Study函数... 359 性能测试... 360 正则表达式调试信息... 361 结语... 363 第8章:Java. 365 Java的正则流派... 366 Java对\p{…}和\P{…}的支持... 369 Unicode行终结符... 370 使用java.util.regex. 371 The Pattern.compile() Factory. 372 Pattern的matcher方法... 373 Matcher对象... 373 应用正则表达式... 375 查询匹配结果... 376 简单查找-替换... 378 高级查找-替换... 380 原地查找-替换... 382 Matcher的检索范围... 384 方法链... 389 构建扫描程序... 389 Matcher的其他方法... 392 Pattern的其他方法... 394 Pattern的split方法,单个参数... 395 Pattern的split方法,两个参数... 396 拓展示例... 397 为Image Tag添加宽度和高度属性... 397 对于每个Matcher,使用多个Pattern校验HTML. 399 解析CSV文档... 401 Java版本差异... 401 1.4.2和1.5.0之间的差异... 402 1.5.0和1.6之间的差异... 403 第9章:.NET. 405 .NET的正则流派... 406 对于流派的补充... 409 使用.NET正则表达式... 413 正则表达式快速入门... 413 包概览... 415 核心对象概览... 416 核心对象详解... 418 创建Regex对象... 419 使用Regex对象... 421 使用Match对象... 427 使用Group对象... 430 静态“便捷”函数... 431 正则表达式缓存... 432 支持函数... 432 .NET高级话题... 434 正则表达式装配件... 434 匹配嵌套结构... 436 Capture对象... 437 第10章:PHP.. 439 PHP的正则流派... 441 Preg函数接口... 443 “Pattern”参数... 444 Preg函数罗列... 449 “缺失”的preg函数... 471 对未知的Pattern参数进行语法检查... 474 对未知正则表达式进行语法检查... 475 递归的正则表达式... 475 匹配嵌套括号内的文本... 475 不能回溯到递归调用之内... 477 匹配一组嵌套的括号... 478 PHP效率... 478 模式修饰符S:“研究”. 478 扩展示例... 480 用PHP解析CSV.. 480 检查tagged data的嵌套正确性... 481 索引...... 485

62,614

社区成员

发帖
与我相关
我的任务
社区描述
Java 2 Standard Edition
社区管理员
  • Java SE
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧