簡體   English   中英

正則表達式匹配轉義字符(引號)

[英]Regular expression to match escaped characters (quotes)

我想構建一個簡單的正則表達式,涵蓋帶引號的字符串,包括其中的任何轉義引號。 例如,

"This is valid"
"This is \" also \" valid"

顯然,像

"([^"]*)"

不起作用,因為它與第一個轉義引號匹配。

什么是正確的版本?

我想其他轉義字符的答案是相同的(只需替換相應的字符)。

順便說一句,我知道“包羅萬象”的正則表達式

"(.*?)"

但我盡量避免它,因為毫不奇怪,它的運行速度比更具體的要慢一些。

這是我過去使用過的一個:

("[^"\\]*(?:\\.[^"\\]*)*")

這將捕獲帶引號的字符串以及任何轉義的引號字符,並排除未出現在封閉引號中的任何內容。

例如,該模式將從該字符串中捕獲"This is valid""This is \\" also \\" valid"

"This is valid" this won't be captured "This is \" also \" valid"

此模式將匹配字符串"I don't \\"have\\" a closing quote ,並允許在字符串中使用額外的轉義碼(例如,它將匹配"hello world!\\n" )。

當然,您必須轉義該模式才能在代碼中使用它,如下所示:

"(\"[^\"\\\\]*(?:\\\\.[^\"\\\\]*)*\")"

所有其他答案的問題在於它們僅與最初的明顯測試相匹配,但不足以進行進一步的審查。 例如,所有答案都希望第一個引用不會被轉義。 但最重要的是,轉義是一個比單個反斜杠更復雜的過程,因為反斜杠本身可以被轉義。 想象一下嘗試實際匹配以反斜杠結尾的字符串。 這怎么可能?

這將是您正在尋找的模式。 它不假設第一個引號是有效的,並且允許轉義反斜杠。

(?<!\\)(?:\\{2})*"(?:(?<!\\)(?:\\{2})*\\"|[^"])+(?<!\\)(?:\\{2})*"

試試這個......它更喜歡\\" ,如果匹配,它會選擇它,否則它會選擇"

"((?:\\"|[^"])*)"

匹配字符串后,您需要獲取第一個捕獲組的值並將\\"替換為"

編輯:固定分組邏輯。

請在下面的代碼中找到包含StringNumberDecimal表達式評估的代碼。

public static void commaSeparatedStrings() {        
    String value = "'It\\'s my world', 'Hello World', 'What\\'s up', 'It\\'s just what I expected.'";

    if (value.matches("'([^\'\\\\]*(?:\\\\.[^\'\\\\])*)[\\w\\s,\\.]+'(((,)|(,\\s))'([^\'\\\\]*(?:\\\\.[^\'\\\\])*)[\\w\\s,\\.]+')*")) {
        System.out.println("Valid...");
    } else {
        System.out.println("Invalid...");
    }
}

/**
 * 
 */
public static void commaSeparatedDecimals() {
    String value = "-111.00, 22111.00, -1.00";
    // "\\d+([,]|[,\\s]\\d+)*"
    if (value.matches(
            "^([-]?)\\d+\\.\\d{1,10}?(((,)|(,\\s))([-]?)\\d+\\.\\d{1,10}?)*")) {
        System.out.println("Valid...");
    } else {
        System.out.println("Invalid...");
    }
}

/**
 * 
 */
public static void commaSeparatedNumbers() {
    String value = "-11, 22, -31";      
    if (value.matches("^([-]?)\\d+(((,)|(,\\s))([-]?)\\d+)*")) {
        System.out.println("Valid...");
    } else {
        System.out.println("Invalid...");
    }
}

("((?:[^"\\])*(?:\\\")*(?:\\\\)*)*")

將捕獲所有字符串(在雙引號內),包括 \\" 和 \\\\ 轉義序列。(請注意,此答案假定您的字符串中唯一的轉義序列是 \\" 或 \\\\ 序列——沒有其他反斜杠字符或轉義序列將被俘虜。)

("(?:         # begin with a quote and capture...
  (?:[^"\\])* # any non-\, non-" characters
  (?:\\\")*   # any combined \" sequences
  (?:\\\\)*   # and any combined \\ sequences
  )*          # any number of times
")            # then, close the string with a quote

在這里試試吧!

另外,請注意, maksymiuk 接受的答案包含一個“邊緣情況”(“想象一下嘗試實際匹配以反斜杠結尾的字符串”),它實際上只是一個格式錯誤的字符串。 就像是

"this\"

...不是“以反斜杠結尾的字符串”,而是以轉義引號結尾的未閉合字符串。 真正以反斜杠結尾的字符串看起來像

"this\\"

...上述解決方案處理這種情況。


如果你想擴展一點,這...

(\\(?:b|t|n|f|r|\"|\\)|\\(?:(?:[0-2][0-9]{1,2}|3[0-6][0-9]|37[0-7]|[0-9]{1,2}))|\\(?:u(?:[0-9a-fA-F]{4})))

...捕獲所有常見的轉義序列(包括轉義引號):

(\\                       # get the preceding slash (for each section)
  (?:b|t|n|f|r|\"|\\)     # capture common sequences like \n and \t

  |\\                     # OR (get the preceding slash and)...
  # capture variable-width octal escape sequences like \02, \13, or \377
  (?:(?:[0-2][0-9]{1,2}|3[0-6][0-9]|37[0-7]|[0-9]{1,2}))

  |\\                     # OR (get the preceding slash and)...
  (?:u(?:[0-9a-fA-F]{4})) # capture fixed-width Unicode sequences like \u0242 or \uFFAD
)

有關第二點的更多信息,請參閱此要點

它對我有用,而且比當前的答案更簡單

(?<!\\+)"(\\"|[^"])*(?<!\\+)"

(?<!\\\\+) - 在"之前不是必須是\\ ,並且這個表達式是左右。

(\\\\"|[^"])* - 引號內:可能是轉義引號\\\\"或任何除了引號[^"]

當前正則表達式可以正確處理以下字符串:

234 - falsenull

"234" - true["234"]

"" - true[""]

"234 + 321 \\\\"24\\\\"" - true["234 + 321 \\\\"24\\\\""]

"234 + 321 \\\\"24\\\\"" + 123 + "\\\\"test(\\\\"235\\\\")\\\\"" - true

["234 + 321 \\\\"24\\\\"", "\\\\"test(\\\\"235\\\\")\\\\""]

"234 + 321 \\\\"24\\\\"" + 123 + "\\\\"test(\\\\"235\\\\")\\\\"\\\\" - true

["234 + 321 \\\\"24\\\\""]

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

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