该字符串虽然是完全有效的JS源代码,但不符合JSON格式。因此,我不认为有一个简单的解决方案,允许使用JSON.parse
。也许我错了
问题
我有一个键值对字符串,并希望使用正则表达式提取它们。
- 钥匙都是已知的
- 分隔符是冒号
- 键可以用单引号或双引号括起来,也可以不用。即
key:value
、'key':value
、"key":value
- 键和分隔符之间可能有空间,也可能没有空间。即
key:value
、key :value
- 分隔符和值之间可能有空格,也可能没有。即
key:value
、key: value
- 该值可以用单引号或双引号括起来,也可以不用。即
key:value
、key:"value"
、key:'value'
- 该值可以由多行文本组成。即
key: {
val1: 1,
val2: 2,
val3: 3,
}
key: [
val1,
val2,
val3,
]
key: (arg1, arg2) => {
return {
arg1,
arg2
}
}
示例
字符串:
value1 : true,
value2 : "something, something-else",
value3: [
{
a: 'a',
b: true,
c: 3
}, {
a: Thing,
func: () => {
return new Thing()
}
}
],
"value4": [1, 2, 3, 4],
'value5': "['a', 'b', 'c', 'd']",
value6: false
型
最后,我想以一个包含键值对的二维数组结束,但是一旦使用正则表达式提取了键和值,就可以处理这个问题。
预期结果:
[
['value1', true],
['value2', 'something, something-else'],
['value3', "{
a: 'a',
b: true,
c: 3
}, {
a: Thing,
func: () => {
return new Thing()
}
}"],
['value4', "[1, 2, 3, 4]"],
['value5', "['a', 'b', 'c', 'd']"],
['value6', false]
[
型
尝试的解决方案
这是我目前为止想到的:
(?<key>value1|value2|value3|value4|value5|value6)["'\s]*?:\s*(?<value>(?!value1|value2|value3|value4|value5).*)
型
1.使用命名的捕获组显式匹配冒号左侧的键-考虑可选的单引号或双引号以及两侧的空格
(?<key>value1|value2|value3|value4|value5|value6)["'\s]*?:
型
1.使用负向前查找将值匹配到下一个键
\s*(?<value>(?!value1|value2|value3|value4|value5).*)
型
但这似乎并没有做我想的那样,就好像你把所有的单词都去掉,用一些任意的东西来代替,结果还是一样的
\s*(?<value>(?!a).*)
型
我意识到这实际上并不是检查换行符,但我不确定如何合并它?
已尝试在regex101上解决问题
有你真好
对于值,只提取可选的单引号或双引号内的内容,而不是引号或逗号。即,该something, something-else
而不是'something, something-else',
备注
regex 101示例被设置为PCRE,以便我可以使用Regex调试器,但我正在寻找使用有效JavaScript正则表达式的解决方案。
4条答案
按热度按时间gcmastyq1#
基于一个正则表达式,比如…
字符串
...如果它的全局多行变体产生matches like shown at this regex playground,则可以选择基于
reduce
的方法,该方法确实处理基于行的令牌,这些令牌是split
在每个换行符处对源字符串进行ting的结果。然后,实现是非常简单的。对于每个行标记,只需要执行regex并尝试访问regex-result的命名捕获组。只要至少
value
捕获确实存在,就有一个有效的匹配,因此,可以将有效的键值对推入OP的结果数组,其中键要么是未加引号的,要么是作为其取消引号的变体捕获的。如果value
为null,则没有任何内容匹配,这表明最后收集的有效键值对的多行值。因此,必须逐行连接后者的值。x
的字符串
如果OP需要不等于上述实现的解析原始结果的问题的请求结果,则上述代码需要伴随有附加的清理任务,该清理任务从每个键值对的值中剥离尾随和前导引号。
编辑
在处理了第一个正则表达式模式之后,我认为找到一个只支持正则表达式的方法并不难。所以在尝试了一点并给了之前...
型
...一个转折,正则表达式可以处理解析本身是...
型
是explanation and how it actually works can be found a this regex' playground。
主要的变化是…
value
组通过非贪婪点全(.*?
)量词捕获多行匹配,(?:^|\n)
和在模式结束处的正向前查找(具有(?=,\n['"\w]|$)
的交替)的组合,这两者都标识键值对的开始和结束,即使它分布在几个换行符上。利用新的模式和适应之前介绍的代码相应地导致以下实现…
wqsoz72f2#
是否知道密钥的顺序?如果是这样,您可以尝试将源字符串从一个键分割到下一个键,然后从每个值的开始和结束处删除不需要的位(空格、换行符、逗号、引号):
字符串
您也可以调整上述范例,以使用未排序的索引键:
型
注意,如果您有许多键,则可能需要通过从键数组中删除已找到的键来优化此代码。
c90pui9n3#
我已经成功地用下面的正则表达式解决了这个问题(它可能可以优化,但它完成了我需要它做的工作):
字符串
它捕获命名组“key”中冒号左侧的键,并允许在键后添加可选的空格或单/双引号:
型
然后,它使用负向前查找来匹配冒号右侧的值,以查找下一个键或字符串的结尾。在它查找的负前瞻之前:
型
工作演示here
型
vptzau2j4#
你得到的数据不是JSON,但看起来像是一个JavaScript对象,去掉了开始的
{
和结束的}
。因此,您可以使用
eval
解析它,但要注意eval
的问题,IOW:确保你相信消息来源你的源代码有一些函数,比如
Thing()
,所以需要stubbing,下面我用了一个小技巧来捕获异常并自动添加Thing
,它在Chrome和Firefox上对我有效,但是解析错误字符串感觉有点笨拙,所以需要注意的是。我注意到你的布尔值的结果没有 Package 在字符串中,所以我做了一个测试,因为我刚刚使用JSON来做值部分,它与你的输出不完全相同,但可以用一个更接近你的目标的自定义部分来代替。
如果需要更详细的信息,我建议使用AST来解析它,
regex
可能也可以,但我觉得它们可能是一些边缘情况,会让您感到困惑。如果您使用AST,不要忘记添加{
和}
来使它可以解析。个字符