【问题标题】:Parsing a String That's Kind of JSON解析 JSON 类型的字符串
【发布时间】:2017-06-05 18:54:54
【问题描述】:

我有一组 JSON 格式的字符串,但完全不符合 JSON 标准。它也是一种 CSV,但值本身有时带有逗号。

字符串如下所示:

ATTRIBUTE:这个属性的值,ATTRIBUTE2:另一个值,但是这个有逗号,ATTRIBUTE3:,另一个值...

我能看到的唯一两种最有效的模式是属性名称大写,后跟一个 : 和空格。在第一个属性之后,模式是 , name-in-caps : space。

数据存储在 Redshift 中,所以我想看看是否可以使用正则表达式来解决这个问题,但我的正则表达式知识有限 - 我该从哪里开始?

如果没有,我会求助于 python hacking。

【问题讨论】:

  • 首先,问问自己:“我想从我的输入中检索什么?”。之后,您可以搜索如何执行此操作。很好,您注意到输入中有一个“模式”,您可以在其上编写正则表达式。
  • 我本质上想检索一个干净的可访问键/值存储,我可以分析或转换为列数据集。答案可能只是:我需要学习正则表达式。
  • 我不介意帮忙。 ;) 您想为正则表达式使用哪种语言?您可以编辑您的问题以添加您在 cmets 中编写的所有信息。
  • 冒号是否出现在ATTRIBUTEValue之间以外的任何地方?

标签: json regex


【解决方案1】:

您所描述的内容类似于:

^([A-Z\d]+?): (.*?), ([A-Z\d]+?): (.*?), ([A-Z\d]+?): (.*)$

虽然这个答案意味着您的第三个属性值实际上并不是以逗号开头,并且您的属性名称可以计算数字。

如果我们采取这个装置:

  • [A-Z\d]大写字母和数字
  • +?: 任意数量,直到第一个 :
  • (.*?), 一个 空格,然后是所需的任意多个字符,直到 coma 和一个 空格
  • ^$ 分别是字符串的开头和结尾

剩下的就是这种模式的重复。

( ) 仅用于标识您的捕获部分,在这种情况下,它们不会直接影响匹配。

Here's a working example

【讨论】:

  • 您的答案不起作用,它将选择第一个大写字母后跟冒号和空格后的所有字符串(即Value of this attribute, ATTRIBUTE2: Another value, but this one has a comma in it, ATTRIBUTE3:, another value
  • 你是对的,虽然给出的例子似乎并不代表需求,因为例子中还有数字,第三个值以逗号开头...... Thie会更好地匹配数字的存在,三个属性,但不是逗号[A-Z\d]+?:\s(.*?), [A-Z\d]+?:\s(.*?), [A-Z\d]+?:\s(.*?)
  • 让我们等待 OP 澄清它的需求。 :)
【解决方案2】:

通常,正则表达式似乎不是正确的工具。

阅读这篇深思熟虑的帖子了解详情:https://softwareengineering.stackexchange.com/questions/223634/what-is-meant-by-now-you-have-two-problems

如果可以使用更简单的方案,请使用它!这是一种可以成功解析结构的方案,只要冒号只出现在属性和值之间,而不是在其中:

代码

static void Main(string[] args)
{
    string data = "ATTRIBUTE: Value of this attribute,ATTRIBUTE2: Another value, but this one has a comma in it,ATTRIBUTE3:, another value,value1,ATTRIBUTE4:end of file";


    Console.WriteLine();
    Console.WriteLine("As an String");
    Console.WriteLine();

    Console.WriteLine(data);

    string[] arr = data.Split(new[] { ":" }, StringSplitOptions.None);

    Dictionary<string, string> attributeNameToValue = new Dictionary<string, string>();

    Console.WriteLine();
    Console.WriteLine("As an Array Split on ':'");
    Console.WriteLine();

    Console.WriteLine("{\"" + String.Join("\",\"", arr) + "\"}");

    string currentAttribute = null;
    string currentValue = null;

    for (int i = 0; i < arr.Length; i++)
    {
        if (i == 0)
        {
            // The first element only has the first attribute name
            currentAttribute = arr[i].Trim();
        }
        else if (i == arr.Length - 1)
        {
            // The last element only has the final value
            attributeNameToValue[currentAttribute] = arr[i].Trim();
        }
        else
        {
            int indexOfLastComma = arr[i].LastIndexOf(",");
            currentValue = arr[i].Substring(0, indexOfLastComma).Trim();
            string nextAttribute = arr[i].Substring(indexOfLastComma + 1).Trim();

            attributeNameToValue[currentAttribute] = currentValue;

            currentAttribute = nextAttribute;
        }
    }

    Console.WriteLine();
    Console.WriteLine("As a Dictionary");
    Console.WriteLine();

    foreach (string key in attributeNameToValue.Keys)
    {
        Console.WriteLine(key + " : " + attributeNameToValue[key]);
    }
}

输出:

作为字符串

ATTRIBUTE:这个属性的值,ATTRIBUTE2:另一个值,但是这个有逗号,ATTRIBUTE3:,另一个值,value1,ATTRIBUTE4:文件结束

作为 ':' 上的数组拆分

{"ATTRIBUTE","这个属性的值,ATTRIBUTE2","另一个值,但是这个有逗号,ATTRIBUTE3",",另一个值,value1,ATTRIBUTE4","文件结束"}

作为字典

ATTRIBUTE : 该属性的值

ATTRIBUTE2 : 另一个值,但这个值中有一个逗号

ATTRIBUTE3 : ,另一个值,value1

ATTRIBUTE4 : 文件结束

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-04-24
    • 2013-09-16
    • 1970-01-01
    相关资源
    最近更新 更多