我有一个包含许多JSON的长字符串,它看起来像:
{"a":"b"}{"c":"d"}{"e":"f"}...
我准备了regex表达式来从这种字符串中检索所有JSON:
\{(?:[^{}]|(?R))*\}
它工作得很好,但它有一个问题。如果在需要检索如下字符串时失败:
{"a":"b"}{"c":"d"}{"e":"f}"}...
它假定,"}" " f"之后的标志字母结束了第三个JSON,但当然不是。你有没有人知道如何解决这个问题?
代码示例: https://regex101.com/r/L9UUzj/1
谢谢!
答案 0 :(得分:2)
[^{}]
不会考虑引号之间的部分,而是可以将其替换为:[^"{}]|"[^"]*"
您可以使用此模式执行此操作:
{[^"{}]*+(?:"[^"]*+"[^"{}]*+|(?R)[^"{}]*+)*+}
此外,如果您想在引用的部分内处理转义引号(带反斜杠):
{[^"{}]*+(?:"[^"\\]*+(?s:\\.[^"\\]*)*+"[^"{}]*+|(?R)[^"{}]*+)*+}
这两种模式使用更高效的展开设计。简而言之,您不必编写(A|B)*
,而是编写需要较少步骤的A*(BA*)*
。
当大括号在字符串中的位置不平衡时,占有量词*+
可以防止大量回溯。这样,模式在这个位置会很快失败。
显然,这两种模式并没有完全描述json语法。可以使用命名组和(?(DEFINE)...)
功能来做到这一点,这远非不可能(*)。但是你也可以使用第二种模式来提取json子串,然后用你选择的json解析器检查它们。
(*)这样的事情:
~
\g<object>
(?(DEFINE)
(?<string> " [^"\\]*+ (?s: \\. [^"\\]*+ )*+ " )
(?<table> \[ (?: \s* \g<value> (?: \s* , \s* \g<value> )*+ )? \s* ] )
(?<object> {
(?: \s* \g<key> \s* : \s* \g<value>
(?: \s* , \s* \g<key> \s* : \s* \g<value> )*+
)? \s* }
)
(?<boolean> [Tt]rue | [Ff]alse )
(?<number> (?: [0-9]+ (?: \. [0-9]* )? | \.[0-9]+ )
(?: [Ee] -? [0-9]+ )? )
(?<key> \g<string> (?<= [^"]" | \\"" ) )
(?<value> \g<table> | \g<object> | \g<string>
| \g<number> | \g<boolean> | null )
)
~x