[英]Java Regex: Replace character unless preceded by other character
我正在使用Java和正則表達式,需要將一些數據拆分為多個實體。 在我的輸入中,單引號(')指定了實體的末尾,除非其前面帶有轉義字符(即問號(?))。
我的RegEx是(?<!\\\\?)\\\\'
,我正在使用掃描儀將輸入拆分為單獨的實體。 因此以下情況可以正常工作:
Hello'There becomes 2 entities: Hello and There
Hello?'There remains 1 entity: Hello?'There
但是,當我遇到要轉義問號的情況時,它不起作用。 所以:
Hello??'There should become 2 entities: Hello?? and There
Hello???'There should become 1 entity: Hello???'There
Hello????'There should become 2 entities: Hello???? and There
Hello?????'There should become 1 entity: Hello????'There
Hello?????There should become 1 entity: Hello????There
Hello??????There should become 1 entity: Hello?????There
因此,規則是如果問號是偶數,后跟引號,則應將其分開。 如果問號數量奇數,則不應拆分。
有人可以解決我的Regex問題(希望有一個解釋!)以應對多種情況嗎?
謝謝,
菲爾
嘗試使用此表達式來匹配偶數情況: (?<=[^\\?](?>\\?\\?){0,1000})'
(?<=...)'
是一個正的外觀behing,即每'
是由之間的表達之前(?<=
和)
將匹配 (?>\\?\\?)
是2個連續問號的原子組 (?>\\?\\?){0,1000}
表示這些組中可以有0到1000。 請注意,您不能編寫(?>\\?\\?)*
因為表達式需要具有最大長度(最大組數)。 但是,根據表達式的其余部分,您應該可以將上限提高很多 [^\\?](?>\\?\\?)...
表示2個問號的組必須以某個字符而不是問號開頭(否則,您將匹配奇數大小寫) 不要為此使用split()
。 這似乎是顯而易見的解決方案,但是匹配實體本身比匹配定界符要容易得多。 大多數啟用正則表達式的語言都為此內置了方法,例如Python的findall()
或Ruby的scan()
,但是在Java中,我們仍然堅持編寫樣板。 這是一個例子:
Pattern p = Pattern.compile("([^?']|\\?.)+");
String[] inputs = {
"Hello??'There",
"Hello???'There",
"Hello????'There",
"Hello?????'There",
"Hello?????There",
"Hello??????There"
};
for (String s : inputs)
{
System.out.printf("%n%s :%n", s);
Matcher m = p.matcher(s);
while (m.find())
{
System.out.printf(" %s%n", m.group());
}
}
輸出:
Hello??'There :
Hello??
There
Hello???'There :
Hello???'There
Hello????'There :
Hello????
There
Hello?????'There :
Hello?????'There
Hello?????There :
Hello?????There
Hello??????There :
Hello??????There
托馬斯使用的任意最大長度的mm頭,除了是令人作嘔的駭客(托馬斯,無意冒犯)外,還是不可靠的,因為他們不斷在處理該問題的Pattern.java代碼中引入錯誤。 但是,不要將此解決方案視為另一種解決方法。 lookbehinds絕對不是您的首選,即使在.NET之類的版本中,lookbehinds可靠且無限制地運行。
您確定要使用正則表達式嗎? 如果您的字符串相對較小和/或執行時間不是大問題,則可以使用字符串生成器和循環來計算“?”的數量 例如
//Your String
String x = "Hello??'World'Hello?'World";
StringBuilder sb = new StringBuilder();
//Holds your splits
ArrayList<String> parts = new ArrayList<String>();
int questionmarkcount = 0;
int _isEven;
for (char c : x.toCharArray()) {
if (c == '?') {
questionmarkcount++;
sb.append(c);
} else if (c == '\'') {
_isEven = questionmarkcount % 2;
//if there are an even number of '? or none
if (_isEven == 0 || questionmarkcount == 0) {
//add the current split, reset the ? count and clear the String builder
parts.add(sb.toString());
sb.delete(0, sb.length());
questionmarkcount = 0;
} else {
//append the question mark, no split is needed
sb.append(c);
//start counting from the beginning
questionmarkcount = 0;
}
} else {
sb.append(c);
}
}
parts.add(sb.toString());
在循環結束時,部分ArrayList將保存所有拆分。 如果'前面有偶數個問號,則當前代碼將拆分。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.