Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/regex/17.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 匹配键值模式正则表达式_Java_Regex - Fatal编程技术网

Java 匹配键值模式正则表达式

Java 匹配键值模式正则表达式,java,regex,Java,Regex,我正在制作一个键值解析器,其中输入字符串的形式为key:“value”,key2:“value”。键可以包含字符a-z,a-z和0-9,值可以包含任何字符,但:,,,“和\需要以反斜杠作为前缀。逗号用于分隔键值对,但在最后一对之后不需要逗号 到目前为止,我已经有了([a-zA-Z0-9]+):“(.*”,它将匹配大多数键和值,但显然它无法处理多个对,或者如果任何“控制”字符未被替换 ([a-zA-Z0-9]+):"(.*?)(?<!\\)" Java正则表达式是 "([a-zA-Z0-

我正在制作一个键值解析器,其中输入字符串的形式为
key:“value”,key2:“value”
。键可以包含字符
a-z
a-z
0-9
,值可以包含任何字符,但
\
需要以反斜杠作为前缀。逗号用于分隔键值对,但在最后一对之后不需要逗号


到目前为止,我已经有了
([a-zA-Z0-9]+):“(.*”
,它将匹配大多数键和值,但显然它无法处理多个对,或者如果任何“控制”字符未被替换

([a-zA-Z0-9]+):"(.*?)(?<!\\)"

Java正则表达式是

"([a-zA-Z0-9]+):\"(.*?)(?<!\\\\)\""
输出:

joe --> Look over there\, it's a shark!
sam --> I like fish.
joe --> Look over there\, i\"t's a shark!
sam --> I like fish.

输出:

joe --> Look over there\, it's a shark!
sam --> I like fish.
joe --> Look over there\, i\"t's a shark!
sam --> I like fish.

假设
\
后跟除行终止符以外的任何字符,则指定紧跟其后的字符

可以使用以下正则表达式匹配键值对的所有实例:

"([a-zA-Z0-9]+):\"((?:[^\\\\\"]|\\\\.)*+)\""
abc:"xyz:"text text", more:"pair"
"(?:^|(?!^)\\G,)([a-zA-Z0-9]+):\"((?:[^\\\\\"]|\\\\.)*+)\""
如果要允许自由间距,请在
之前和之后添加
\\s*

这是正则表达式引擎看到的:

([a-zA-Z0-9]+):"((?:[^\\"]|\\.)*+)"
量词
*
被设置为所有格
*+
,因为
[^\\“]
\.
这两个分支是互斥的(没有字符串可以同时被两者匹配)。它还避免了Oracle实现
模式
类时出现的
堆栈溢出错误

在匹配器循环中使用上面的正则表达式:

Pattern keyValuePattern = Pattern.compile("([a-zA-Z0-9]+):\"((?:[^\\\\\"]|\\\\.)*+)\"");
Matcher matcher = keyValuePattern.matcher(inputString);

while (matcher.find()) {
    String key = matcher.group(1);

    // Process the escape sequences in the value string
    String value = matcher.group(2).replaceAll("\\\\(.)", "$1");

    // ...
}
在一般情况下,根据转义序列的复杂性(例如,
\n
\uhhh
\xhh
\0
),您可能需要编写一个单独的函数来解析它们。但是,根据上述假设,一行代码就足够了

请注意,此解决方案并不关心分隔符。它将跳过无效输入,直到最接近的匹配。在下面的无效输入示例中,上面的解决方案将跳过开头的
abc:
,并愉快地匹配
xyz:“text text”
amd
more:“pair”
作为键值对:

"([a-zA-Z0-9]+):\"((?:[^\\\\\"]|\\\\.)*+)\""
abc:"xyz:"text text", more:"pair"
"(?:^|(?!^)\\G,)([a-zA-Z0-9]+):\"((?:[^\\\\\"]|\\\\.)*+)\""
如果不希望出现这种行为,则有一种解决方案,但必须首先隔离包含所有键值对的字符串,而不是与键值对无关的较大字符串的一部分:

"([a-zA-Z0-9]+):\"((?:[^\\\\\"]|\\\\.)*+)\""
abc:"xyz:"text text", more:"pair"
"(?:^|(?!^)\\G,)([a-zA-Z0-9]+):\"((?:[^\\\\\"]|\\\\.)*+)\""
自由间距版本:

"(?:^\s*|(?!^)\\G\s*,\s*)([a-zA-Z0-9]+)\s*:\s*\"((?:[^\\\\\"]|\\\\.)*+)\""

您可以提供一个示例以及预期的输出吗?为什么不
input\u string.split(“,”
然后循环结果和
result.split(“:”)
然后在循环中有键->值对可以随意操作。新行可以是值的一部分吗?它是如何在值中指定的?@nhatdh任何字符都可以是值的一部分,并将被表示为它自己,除非它需要加前缀“\”,因为它是格式的一部分。@gwillie我想我可以这样做,但我需要它获取“,”的索引,并检查它是否首先被转义。仍然存在问题,但我意识到,由于问题没有明确说明,所以没有必要对答案进行向下投票。顺便说一下,您的正则表达式在
abc:“value\\”
中会失败,为什么不使用通常的
(?:[^\\”]*+\124\\)*+
?您的解决方案非常脆弱。他无法描述转义字符。@AvinashRaj这将匹配包含字符的值,例如
“\,:
不带反斜杠前缀。在我的情况下,这在大多数情况下是可以的,但这意味着它将接受格式不正确的字符串,您知道解决方法吗?我最终将字符串拆分为键值对,然后使用
([a-zA-Z0-9]+):”(((?:\[:“\,]”124;[^:“\,]”)*)$
感谢您的回答。如果出现问题,首先拆分它可以让我给出一个更具描述性的错误。我不确定这是否是最有效的方法,但它似乎适用于我遇到的所有测试用例,并拒绝任何格式错误。