[英]Java regex backreference for two digits
我正在使用正則表達式,並且想在Java中String類的replaceAll
方法上使用它。
我的正則表達式可以正常工作,並且groupCount()
返回11。因此,當我嘗試使用指向第11個組的后向引用替換文本時,我得到的第一個組帶有附加的“ 1”,而不是第11個組。
String regex = "(>[^<]*?)((\+?\d{1,4}[ \t\f\-\.](\d[ \t\f\-\.])?)?(\(\d{1,4}([\s-]\d{1,4})?\)[\.\- \t\f])?((\d{2,6}[\.\- \t\f])+\d{2,6})|(\d{6,16})([;,\.]{1,3}\d{3,}#?)?)([^<]*<)";
String text = "<span style=\"font-size:11.0pt\">675-441-3144;;;78888464#<o:p></o:p></span>":
String replacement = text.replaceAll(regex, $1<a href="tel:$2">$2</a>$11");
我期望得到以下結果:
<span style=\"font-size:11.0pt\"><a href=\"tel:675-441-3144;;;78888464#\">675-441-3144;;;78888464#</a><o:p></o:p></span>
但是$ 11的反向引用沒有返回第11個組,而是返回了第一個附加了1的組,相反,我得到了以下結果:
<span style="font-size:11.0pt"><a href="tel:675-441-3144">675-441-3144</a>>1o:p></o:p></span>
有人可以告訴我如何訪問我的模式的第11組嗎?
謝謝。
訪問替換中比賽的第十一組的方式是使用$11
。
如相應的Javadoc *所述:
替換字符串可能包含對先前匹配過程中捕獲的子序列的引用:
${name}
或$g
每次出現都將被分別評估相應group(name)或group(g)的結果替換。 對於$g
,在之后的第一個數字$
始終被視為該組參考的一部分。 如果后續數字將構成合法的組引用,則將其合並到g
。
因此,一般來講,只要至少有11個組,則"$11"
將評估為group(11)
。 但是,如果您沒有至少11個組,則"$11"
將計算為group(1) + "1"
。
* 此引用來自Matcher#appendReplacement(StringBuffer,String)
,這是來自String#replaceAll(String,String)
的相關引用鏈的所在。
您的正則表達式不會執行您認為的操作。
讓我們將正則表達式分為三個頂級組。 它們分別是組1、2和11。
(>[^<]*?)
((\\+?\\d{1,4}[ \\t\\f\\-\\.](\\d[ \\t\\f\\-\\.])?)?(\\(\\d{1,4}([\\s-]\\d{1,4})?\\)[\\.\\- \\t\\f])?((\\d{2,6}[\\.\\- \\t\\f])+\\d{2,6})|(\\d{6,16})([;,\\.]{1,3}\\d{3,}#?)?)
([^<]*<)
第2組是您的正則表達式的主體,它由兩個選項的頂級交替組成。 這兩個選項分別由3-8組和9-10組組成。
((\\+?\\d{1,4}[ \\t\\f\\-\\.](\\d[ \\t\\f\\-\\.])?)?(\\(\\d{1,4}([\\s-]\\d{1,4})?\\)[\\.\\- \\t\\f])?((\\d{2,6}[\\.\\- \\t\\f])+\\d{2,6})
(\\d{6,16})([;,\\.]{1,3}\\d{3,}#?)?)
現在,給定text
字符串,這是怎么回事:
">"
相匹配。 "675-441-3144"
。 "675-441-3144"
。 "675-441-3144"
";;;78888464#"
之前的";;;78888464#"
。 "<"
匹配所有內容;下一個"<"
是所有";;;78888464#<"
。 因此,您希望放在第2組中的某些內容實際上是在第11組中。
請同時執行以下兩項操作:
將第2組的內容轉換為
option1|option2
至
option1(option2)?|option2
將替換模式中的$11
更改$11
$12
。
這會使貪婪地匹配一個或兩個選項,而不是只有一個選項。 替換模式的修改是因為我們添加了一個組。
現在,我們已經修改了正則表達式,原來的“選項2”不再有意義。 給定我們新的模式模板option1(option2)?|option2
,第2組將不可能匹配"675-441-3144;;;78888464#"
。 這是因為我們原來的“選項1”將匹配所有"675-441-3144"
,然后停止。 然后,我們原始的“選項2”將嘗試匹配";;;78888464#"
,但將無法匹配,因為它以6-10位數字的強制捕獲組開頭: (\\d{6,16})
,但";;;78888464#"
以分號開頭。
將原始“選項2”的內容轉換為
(\d{6,16})([;,\.]{1,3}\d{3,}#?)?
至
([;,\.]{1,3}\d{3,}#?)?
我們還有最后一個問題要解決。 現在,我們原來的“選項2”僅包含一個帶有?
組?
量詞,它有可能成功匹配零長度子串。 因此,我們的模式模板option1(newoption2)?|newoption2
可能會導致長度為零的匹配,這不能滿足匹配電話號碼的預期目的。
請執行以下兩個操作:
將新的“選項2”的內容轉換為
([;,。] {1,3} \\ d {3,}#?)?
至
[;,。] {1,3} \\ d {3,}#?
將替換字符串中的$12
更改$12
$10
,因為現在我們已在兩個位置刪除了一個組。
綜上所述,我們最終的解決方案如下。
搜索正則表達式:
(>[^<]*?)((\+?\d{1,4}[ \t\f\-\.](\d[ \t\f\-\.])?)?(\(\d{1,4}([\s-]\d{1,4})?\)[\.\- \t\f])?((\d{2,6}[\.\- \t\f])+\d{2,6})([;,\.]{1,3}\d{3,}#?)?|[;,\.]{1,3}\d{3,}#?)([^<]*<)
替換正則表達式:
$1<a href="tel:$2">$2</a>$10
Java:
final String searchRegex = "(>[^<]*?)((\\+?\\d{1,4}[ \\t\\f\\-\\.](\\d[ \\t\\f\\-\\.])?)?(\\(\\d{1,4}([\\s-]\\d{1,4})?\\)[\\.\\- \\t\\f])?((\\d{2,6}[\\.\\- \\t\\f])+\\d{2,6})([;,\\.]{1,3}\\d{3,}#?)?|[;,\\.]{1,3}\\d{3,}#?)([^<]*<)";
final String replacementRegex = "$1<a href=\"tel:$2\">$2</a>$10";
String text = "<span style=\"font-size:11.0pt\">675-441-3144;;;78888464#<o:p></o:p></span>";
String replacement = text.replaceAll(searchRegex, replacementRegex);
好吧,在嘗試使用replaceall而不成功之后,我不得不自己實現替換方法:
public static String parsePhoneNumbers(String html){
StringBuilder regex = new StringBuilder(120);
regex.append("(>[^<]*?)(")
.append("((\+?\d{1,4}[ \t\f\-\.](\d[ \t\f\-\.])?)?")
.append("(\(\d{1,4}([\s-]\d{1,4})?\)[\.\- \t\f])?")
.append("((\d{2,6}[\.\- \t\f])+\d{2,6})|(\d{6,16})")
.append("([;,\.]{1,3}\d{3,}#?)?)")
.append(")+([^<]*<)");
StringBuilder mutableHtml = new StringBuilder(html.length());
Pattern pattern = Pattern.compile(regex.toString());
Matcher matcher = pattern.matcher(html);
int start = 0;
while(matcher.find()){
mutableHtml.append(html.substring(start, matcher.start()));
mutableHtml.append(matcher.group(1)).append("<a href=\"tel:")
.append(matcher.group(2)).append("\">").append(matcher.group(2))
.append("</a>").append(matcher.group(matcher.groupCount()));
start = matcher.end();
}
mutableHtml.append(html.substring(start));
return mutableHtml.toString();
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.