评论

收藏

[Java] Java正则表达式匹配不到结果的解决

编程语言 编程语言 发布于:2021-08-16 17:55 | 阅读数:504 | 评论:0

如下所示:
String str = "\uFEFF<?xml version="1.0" encoding="utf-8"?><Response xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"><Header ShouldRecordPerformanceTime="false" Timestamp="2018-6-25 21:24:03" RequestID="2c4d0b24-fd48-4a92-a2d8-c66793df2059" ResultCode="Success" AssemblyVersion="2.9.5.0" RequestBodySize="0" SerializeMode="Xml" RouteStep="1" Environment="pro" /><SSPATResponse><Result>0</Result><FareDetail /><Price>0</Price><ErrCode>102</ErrCode><DetailInfo>Send:APPLOCK\n" +
  "Rev:\n" +
  "可用资源锁定成功, 60 秒内没有输入指令资源将被Buk收回\n" +
  "Send:IG\n" +
  "Rev:\n" +
  "NO PNR\n" +
  "Send:\n" +
  "SS:AA186/N/27JUN18/PEKORD/NN1;\n" +
  "Rev:\n" +
  "AA 186 N 27JUN PEKORD NN1 WL OPEN \n" +
  "UNABLE TO SELL.PLEASE CHECK THE AVAILABILITY WITH "AV" AGAIN\n" +
  "Send:IG\n" +
  "Rev:</DetailInfo><PatOfficeno>SHA717</PatOfficeno></SSPATResponse><ResponseStatus><Timestamp xmlns="http://soa.ctrip.com/common/types/v1">2018-06-25T21:24:03.4535624+08:00</Timestamp><Ack xmlns="http://soa.ctrip.com/common/types/v1">Success</Ack></ResponseStatus></Response>";
 
String regex = "<DetailInfo>((.|\\n")*?)</DetailInfo>";
str为要匹配的字符串(是传入的),regex为正则表达式
目的是匹配出<DetailInfo>标签中的内容
在本地测试时可以匹配出来,但是在线上就不行。
真的是百思不得其解……
后来认真比对了一下线上传入的str和本地复制过来的str,发现了了一个微小的不同
线上传入的str行分隔符是\r\n,而复制粘贴到本地之后都变成了\n
而我的正则表达式中只匹配了\n的情况,因此出现这样的bug
提醒自己要注意系统之间的差别,win上的行分隔符是\n,而Linux是\r\n
为了能适配所有的环境,可以直接用System.lineSeparator()来替代,当然也可以把表达式写成这样(
<DetailInfo>((.|\\n|\\r\\n")*?)</DetailInfo>
补充:Java正则表达式匹配的坑
今天在判断字符串是否存在某个字符串,直接用String.matches(regex),死活匹配不出来,在线正则工具用了很多都是可以的,后面找到问题,总结一下,防止再次踩坑。
一、前提#
java中判断一段字符串中是否包含某个字符串的方式:
1、#
String.matches(regex);
阅读源码发现,这个方法本质是调用了Pattern.matches(regex, str),而该方法调Pattern.compile(regex).matcher(input).matches()方法,而Matcher.matches()方法试图将整个区域与模式匹配,如果匹配成功,则可以通过开始、结束和组方法获得更多信息。
即这个方法会在表达式前后加上$(regex$),是对这个字符串全匹配
而不会只匹配其中的子串,如果只想匹配子串,则需要表达式匹配整段
2、#
Pattern.compile(regex).matcher(str).find()
Matcher.find()方法则是仅仅进行匹配字串的方法
如果不想使用全局匹配则可以使用Matcher.find()方法
二、附源码#
1、String.matches(regex)#
String.matches(regex)
public boolean matches(String regex) {
  return Pattern.matches(regex, this);
}
Pattern.matches(regex, this)
public static boolean matches(String regex, CharSequence input) {
  Pattern p = Pattern.compile(regex);
  Matcher m = p.matcher(input);
  return m.matches();
}
2、Matcher.find()#
Pattern.compile
public static Pattern compile(String regex) {
  return new Pattern(regex, 0);
}
Pattern.matcher
public Matcher matcher(CharSequence input) {
  if (!compiled) {
    synchronized(this) {
    if (!compiled)
      compile();
    }
  }
  Matcher m = new Matcher(this, input);
  return m;
}
Matcher.find()
public boolean find() {
  int nextSearchIndex = last;
  if (nextSearchIndex == first)
    nextSearchIndex++;
  // If next search starts before region, start it at region
  if (nextSearchIndex < from)
    nextSearchIndex = from;
  // If next search starts beyond region then it fails
  if (nextSearchIndex > to) {
    for (int i = 0; i < groups.length; i++)
    groups[i] = -1;
    return false;
  }
  return search(nextSearchIndex);
}
三、总结#
各个匹配的优缺点都有,大家可以按需选择
如果仅仅只需要获取字符串中是否包含某个字符串,还是用Matcher.find()比较方便
以上为个人经验,希望能给大家一个参考,也希望大家多多支持CodeAE代码之家
。如有错误或未考虑完全的地方,望不吝赐教。
原文链接:https://blog.csdn.net/z3278221/article/details/80808391

关注下面的标签,发现更多相似文章