繁体   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