簡體   English   中英

Java Regex:替換字符,除非前面有其他字符

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM