java 正则表达式匹配转义字符(引号)

mnemlml8  于 2023-05-12  发布在  Java
关注(0)|答案(6)|浏览(152)

我想构建一个简单的正则表达式,它包含带引号的字符串,包括其中的转义引号。比如说

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

很明显,类似于

"([^"]*)"

不起作用,因为它与第一个转义引号匹配。
正确的版本是什么?
我想对于其他转义字符的答案也是一样的(只需替换相应的字符)。
顺便说一句,我知道“包罗万象”正则表达式

"(.*?)"

但我尽可能避免它,因为,毫不奇怪,它运行得比更具体的慢一些。

rjee0c15

rjee0c151#

以下是我过去使用过的一个:

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

这将捕获带引号的字符串,沿着任何转义的引号字符,并排除任何未出现在封闭引号中的字符。
例如,模式将从以下字符串中捕获"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")。
当然,你必须转义模式才能在代码中使用它,如下所示:

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

h22fl7wq2#

所有其他答案的问题是,它们只符合最初的明显测试,但不足以进行进一步的审查。例如,所有的答案都期望第一个引用不会被转义。但最重要的是,转义是一个比单个反斜杠更复杂的过程,因为反斜杠本身也可以转义。想象一下,试图实际匹配一个以反斜杠结尾的字符串。这怎么可能?
这将是你正在寻找的模式。它并不假定第一个引号是有效的引号,并且允许转义反斜杠。

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

说明:
(?<!\\)后面没有反斜杠(以确保我们从第一个开始匹配)
(?:\\{2})*任意数量的双反斜杠(它们相互无效)
"报价字符
(?:打开组
(?<!\\)后面没有反斜杠(以确保我们从第一个开始匹配)
(?:\\{2})*任意数量的双反斜杠(它们相互无效)
\\" Escaped引号字符(因为引号中允许使用这些字符)
|
[^"]除引号字符以外的任何字符
)关闭组
+组匹配的1个或多个
(?<!\\)后面没有反斜杠(以确保我们从第一个开始匹配)
(?:\\{2})*任意数量的双反斜杠(它们相互无效)
"报价字符

cotxawn7

cotxawn73#

试试这个...它更喜欢\",如果匹配,它将选择它,否则它将选择"

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

匹配字符串后,需要获取第一个捕获组的值,并将\"替换为"
编辑:固定分组逻辑。

nwsw7zdq

nwsw7zdq4#

请在下面的代码中找到包含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...");
    }
}
px9o7tmv

px9o7tmv5#

这一

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

将捕获所有字符串(在双引号内),包括"和\转义序列。(注意,这个答案假设字符串中 * only * 转义序列是"或\序列--不会捕获其他反斜杠字符或转义序列。)

("(?:         # 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's accepted answer包含一个“edge case”(“想象一下,试图实际匹配一个以反斜杠结尾的字符串”),它实际上只是一个格式错误的字符串。就像

"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
)

有关第二点的更多信息,请参见this Gist

of1yzvn4

of1yzvn46#

它对我有效,它比目前的答案简单

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

(?<!\\+)-"之前不一定是\,此表达式为左和右。
(\\"|[^"])*-在引号内:可能是转义引号\\"或除引号[^"]以外的任何字符
当前的正则表达式对以下字符串正确工作:
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\\""]

相关问题