需要解析文件并从中创建数据结构 [已关闭]

Need to parse a file and create a data structure out of it [closed]

提问人:Alok 提问时间:9/30/2023 最后编辑:tripleeeAlok 更新时间:10/1/2023 访问量:85

问:


想改进这个问题吗?更新问题,使其仅通过编辑这篇文章来关注一个问题。

上个月关闭。

我们想解析一个文件并创建一个某种数据结构供以后使用(在 Python 中)。 文件的内容如下所示:

plan HELLO
   feature A 
       measure X :
          src = "Type ,N ame"
       endmeasure //X

       measure Y :
        src = "Type ,N ame"
       endmeasure //Y

       feature Aa
           measure AaX :
              src = "Type ,N ame"
           endmeasure //AaX

           measure AaY :
              src = "Type ,N ame"
           endmeasure //AaY
           
           feature Aab
              .....
           endfeature // Aab
         
       endfeature //Aa
 
   endfeature // A
   
   feature B
     ......
   endfeature //B
endplan

plan HOLA
endplan //HOLA

因此,有一个文件包含一个或多个计划,然后每个计划包含一个或多个功能, 此外,每个功能都包含一个包含信息(src、type、name)的度量值,并且功能可以进一步包含更多功能。

我们需要解析文件并创建一个数据结构,该结构将具有

                     plan (HELLO) 
            ------------------------------
             ↓                          ↓ 
          Feature A                  Feature B
  ----------------------------          ↓
   ↓           ↓             ↓           ........
Measure X    Measure Y    Feature Aa
                         ------------------------------
                            ↓           ↓             ↓ 
                       Measure AaX   Measure AaY   Feature Aab
                                                        ↓
                                                        .......

我正在尝试逐行解析文件并创建一个列表列表,其中包含 计划 -> 功能 ->度量、功能

python 列表 数据结构 readlines fileparse

评论

4赞 Rufus 9/30/2023
此处的问题应首先显示您已经尝试过的内容,以便我们可以改进您当前的解决方案。
0赞 Joran Beasley 9/30/2023
这感觉像是 pyparsing 有好处的东西......
1赞 Rufus 9/30/2023
但作为初学者,您可以使用 .然后,您可以在 for 循环中遍历这些行。with open(file_path, 'r') as f: lines = f.read_lines()
3赞 tripleee 10/1/2023
如果可以避免的话,你真的不想编写和维护自己的解析器。能否说服生成这些文件以标准的机器可读格式(如 JSON、YAML 或 XML)输出?
0赞 Serge Ballesta 10/1/2023
您必须在此处构建一个自定义解析器。不是很复杂,但问题的一个主要来源是词法部分:关键字(feature、endfeature 等)可以出现在带引号的字符串中吗?带引号的字符串可以包含具有特定语法的引号吗?如果答案是肯定的,那么在分析其他任何内容之前,您确实必须仔细检测引号字符串的开头和结尾。pyparsing或PLY等工具可以在这方面提供帮助。当然,如果语法要简单得多(字符串中只有一组有限的元素,并且没有接近关键字的内容),则可以手动构建解析器。

答:

-1赞 gog 10/1/2023 #1

为了快速而肮脏的解析,您可以进行一些正则表达式替换,例如

text = re.sub(
    r'(?mx)^ \s* (plan|feature|measure) \s+ (\w+) .*',
    r'<\1 name="\2">',
    text)
text = re.sub(
    r'(?mx)^ \s* end (plan|feature|measure) .*',
    r'</\1>',
    text)
text = re.sub(
    r'(?mx)^ \s* (\w+) \s*=\s* (.*)',
    r'<\1>\2</\1>',
    text)

这会将其转换为 XML,您可以使用内置工具(例如 ETree)对其进行解析。

0赞 trincot 10/1/2023 #2

下面是一个函数,可以将字符串转换为字典:

def getplans(s):
    stack = [{}]
    for line in s.splitlines():
        if "=" in line:  # leaf
            key, value = line.split("=", 1)
            stack[-1][key.strip()] = value.strip(' "')
        elif line.strip()[:3] == "end":
            stack.pop()
        elif line.strip():
            collection, name, *_ = line.split()
            stack.append({})
            stack[-2].setdefault(collection + "s", {})[name] = stack[-1]
    return stack[0]

下面是一个示例调用:

s = """plan HELLO
   feature A 
       measure X :
          src = "Type, Name"
       endmeasure //X

       measure Y :
        src = "Type, Name"
       endmeasure //Y

       feature Aa
           measure AaX :
              src = "Type, Name"
           endmeasure //AaX

           measure AaY :
              src = "Type, Name"
           endmeasure //AaY
           
           feature Aab
                measure Car :
                  src = "Model, Make"
               endmeasure //car
           endfeature // Aab
         
       endfeature //Aa
 
   endfeature // A
   
   feature B
       measure Hotel :
          src = "Stars, Reviews"
       endmeasure //Hotel
    endfeature //B
endplan

plan HOLA
endplan //HOLA
"""

import json
print(json.dumps(getplans(s), indent=4))

输出:

{
    "plans": {
        "HELLO": {
            "features": {
                "A": {
                    "measures": {
                        "X": {
                            "src": "Type ,N ame"
                        },
                        "Y": {
                            "src": "Type ,N ame"
                        }
                    },
                    "features": {
                        "Aa": {
                            "measures": {
                                "AaX": {
                                    "src": "Type ,N ame"
                                },
                                "AaY": {
                                    "src": "Type ,N ame"
                                }
                            },
                            "features": {
                                "Aab": {
                                    "measures": {
                                        "Car": {
                                            "src": "Model, Make"
                                        }
                                    }
                                }
                            }
                        }
                    }
                },
                "B": {
                    "measures": {
                        "Hotel": {
                            "src": "Stars, Reviews"
                        }
                    }
                }
            }
        },
        "HOLA": {}
    }
}

如果你的输入有其他语法 - 不包括在你的问题中 - 你可能需要进一步调整脚本来处理它。

评论

0赞 Alok 10/4/2023
您能否提供一些想法,例如,如果有多个措施。测量 AaY : src = “Type, Name” “Type, Name2” “Type,Name3”。....endmeasure //AaY
0赞 trincot 10/4/2023
然后,您应该在分配给它之前检查它是否已经存在。如果存在,则将字符串累积到列表中,而不是赋值。如果你不能让它工作,那么也许在一个新的问题中提出你的尝试。stack[-2].setdefault(collection + "s", {})[name]src
0赞 Alok 10/5/2023
你能在这里检查一下吗,我在最后用这种方法丢失了一些数据 stackoverflow.com/questions/77232363/......