好吧,有了更新问题中的嵌套引号,事情就变得更加棘手了。我看不到任何可行的方法来提取具有任意级别的嵌套引号的值。 (这对于正则表达式方法是正确的——仍然可以手动扫描字符串并计算与嵌套级别相关的后续引号的数量。)
假设我们只使用一层嵌套的引号字符串,那么正则表达式将是:
(?<key>[^=,\s]+)=(?:"(?<value>(?:[^"]|""[^"]*"")*?)"|(?<value>[^,]*))(?:,|$)
然后您可以找到所有匹配项并根据 JSON 规则重新格式化对:
var input = @"KEY1=someValue, KEY2=""Hello, World!"",
SOME.OTHER.KEY=Hello ""World""!,
KEY4=""Hello, """"World""""!"",
KEY5=""Hello, """"World""""!"",
KEY6=""""""Hello"""", """"World""""!""";
var pairs = Regex.Matches(input, @"(?<key>[^=,\s]+)=(?:""(?<value>(?:[^""]|""""[^""]*"""")*?)""|(?<value>[^,]*))(?:,|$)")
.Cast<Match>()
.Select(m =>
string.Format(" {0}: {1}",
JsonConvert.ToString(m.Groups["key"].Value),
JsonConvert.ToString(m.Groups["value"].Value.Replace("\"\"", "\""))));
var json = "{\n" + string.Join(",\n", pairs) + "\n}";
正则表达式解释:
-
(?<key> - 启动一个名为 key 的捕获组
-
[^=,\s]+ - 匹配除=、, 和空格之外的任何非空字符序列
-
) - 结束 key 组
-
= - 从字面上匹配等号
-
(?: - 启动一个未命名的组,用于对备选方案进行分组
- 第一个选择 - 引用值:
-
" - 开场白
-
(?<value> - 启动一个名为 value 的捕获组
-
(?:[^"]|""[^"]*"")* - 匹配任何非引号序列或带引号的字符串(请不要将引号加倍)
-
? - 使之前的匹配不贪心
-
) - 结束 value 组
-
" - 文字结束引号
-
| - 替代分隔符
- 第二种选择 - 未引用的值:
-
(?<value> - 启动另一个 value 捕获组 - .NET 正则表达式风格维护一组命名组,因此您可以简单地按名称访问任一替代捕获组
-
[^,]* - 匹配任何不包含逗号的序列
-
) - 结束第二个 value 组
-
) - 结束未命名的组
-
(?:,|$) - 匹配逗号或字符串结尾(都应完成值)