[英]Regex matching unescaped commas in Java
問題描述
我試圖使用String類提供的split()方法將a拆分為單獨的字符串。 文檔告訴我它將分割參數的匹配,這是一個正則表達式。 我使用的分隔符是逗號,但逗號也可以轉義。 我使用的轉義字符是正斜杠/(只是為了通過不使用反斜杠來簡化操作,因為這需要在Java和正則表達式中的字符串文字中進行額外的轉義)。
例如,輸入可能是這樣的:
a,b/,b//,c///,//,d///,
輸出應該是:
a
b,b/
c/,/
d/,
因此,字符串應該在每個逗號處拆分,除非該逗號前面有奇數個斜杠(1,3,5,7,...,∞),因為這意味着逗號被轉義。
可能的解決方案
我最初的猜測是將它拆分為:
String[] strings = longString.split("(?<![^/](//)*/),");
但這是不允許的,因為Java不允許無限的后視組。 我可以通過用{0,2000}替換*來將重現限制為,例如,2000:
String[] strings = longString.split("(?<![^/](//){0,2000}/),");
但這仍然會對輸入產生限制。 因此,我決定將這一反復出現在后視組中,並想出了這個:
String[] strings = longString.split("(?<!/)(?:(//)*),");
但是,它的輸出是以下字符串列表:
a
b,b (the final slash is lacking in the output)
c/, (the final slash is lacking in the output)
d/,
為什么在第2和第3個字符串中省略了這些斜杠,我該如何解決它(在Java中)?
您可以使用正面外觀在逗號前面加上偶數個斜杠來實現拆分:
String[] strings = longString.split("(?<=[^/](//){0,999999999}),");
但要顯示所需的輸出,您需要進一步刪除剩余的轉義:
String longString = "a,b/,b//,c///,//,d///,";
String[] strings = longString.split("(?<=[^/](//){0,999999999}),");
for (String s : strings)
System.out.println(s.replaceAll("/(.)", "$1"));
輸出:
a
b,b/
c/,/
d/,
你很近。 要克服lookbehind錯誤,您可以使用此解決方法:
String[] strings = longString.split("(?<![^/](//){0,99}/),")
如果您不介意使用正則表達式的另一種方法,我建議使用.matcher
:
Pattern pattern = Pattern.compile("(?:[^,/]+|/.)+");
String test = "a,b/,b//,c///,//,d///,";
Matcher matcher = pattern.matcher(test);
while (matcher.find()) {
System.out.println(matcher.group().replaceAll("/(.)", "$1"));
}
輸出:
a
b,b/
c/,/
d/,
此方法將匹配除分隔逗號之外的所有內容(反向類型)。 優點是它不依賴於外觀。
我喜歡正則表達式,但在這里手動編寫代碼並不容易,即
boolean escaped = false;
for(int i = 0, len = s.length() ; i < len ; i++){
switch(s.charAt(i)){
case "/": escaped = !escaped; break;
case ",":
if(!escaped){
//found a segment, do something with it
}
//Fallthrough!
default:
escaped = false;
}
}
// handle last segment
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.