使用JavaScript解析QML文件转JSON的正则替换问题求助
解决QML转JSON时的字符串引号包裹问题
我明白你在解析QML转JSON格式时遇到的正则难题了——要把那些没被双引号包裹的键和值都加上引号,同时避开已经在引号里的内容对吧?你的当前正则有两个明显的坑,咱们一步步来解决它。
先说说你现有正则的问题
- 引号导致匹配中断:你用的
(?![^"]*")负向预查逻辑有问题——它会在遇到第一个双引号后,认为该行后续内容都在引号范围内,直接停止匹配,这就是为啥一行里有引号后其他单词都不被匹配的原因。 - 分组逻辑混乱:
((\S\.\S)|\w+?)的分组设计太模糊,\S\.\S只能匹配单个字符+点+单个字符的情况(比如a.b),没法覆盖Layout.fillHeight这种多段的标识符,而且分组嵌套导致$1和$2的指向不明确,替换时自然拿不到正确内容。
给出解决方案
我们的核心思路是:跳过所有双引号包裹的内容,只在引号外的区域匹配需要加引号的键和值。下面是经过验证的正则和替换逻辑:
// 示例输入 const qmlInput = 'Layout.fillHeight: true height: 200 color: "transparent"'; // 执行替换 const jsonLikeOutput = qmlInput.replace( /(?<!")(\w+(?:\.\w+)*)(?=\s*:)|(?<=:\s*)(?!")(\w+|\d+)(?=\s*(?:\w|$))/g, '"$1$2"' ); console.log(jsonLikeOutput); // 输出:"Layout.fillHeight": "true" "height": "200" "color": "transparent"
正则逻辑拆解
这个正则分成两个分支,分别匹配键和未被引号包裹的值:
- 匹配键的分支:
(?<!")(\w+(?:\.\w+)*)(?=\s*:)(?<!"):确保当前位置前面没有双引号(排除已经被引号包裹的内容)\w+(?:\.\w+)*:匹配QML的标识符,支持带点的多级命名(比如Layout.fillHeight)(?=\s*:):确保后面跟着冒号(允许冒号前有空格)
- 匹配值的分支:
(?<=:\s*)(?!")(\w+|\d+)(?=\s*(?:\w|$))(?<=:\s*):确保当前位置前面是冒号加空格(匹配冒号后的内容)(?!"):确保当前位置不是双引号的开头(排除已经被引号包裹的值)\w+|\d+:匹配单词型值(比如true)或数字型值(比如200)(?=\s*(?:\w|$)):确保后面是空格、下一个键的开头或者行尾(避免误匹配其他内容)
- 替换逻辑:
"$1$2",因为每次匹配只会命中两个分支中的一个,所以$1或$2必有一个为空,拼接后就是正确的带双引号的内容。
边界情况适配
这个正则已经覆盖了常见的QML场景:
- 支持带点的多级键名(比如
Layout.fillWidth) - 支持数字值、布尔值(
true/false) - 自动跳过已经被双引号包裹的内容
- 支持键和值之间的任意空格
如果你的QML还有更复杂的场景(比如负数、带下划线的键名),这个正则也能直接适配,因为\w已经包含了下划线,负数的话可以把值的匹配部分改成-?\d+即可。
内容的提问来源于stack exchange,提问作者sgrumo
相关产品推荐
相关产品推荐

