Java正則表達式匹配不到結果的解決
如下所示:
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()比較方便
以上為個人經驗,希望能給大傢一個參考,也希望大傢多多支持WalkonNet。如有錯誤或未考慮完全的地方,望不吝賜教。
推薦閱讀:
- Java Pattern與Matcher字符串匹配案例詳解
- Java正則表達式之分組和替換方式
- Java中Pattern用法實例(正則表達式)
- 如何在Java中使用正則表達式API
- java 如何判斷是否是26個英文字母