【问题标题】:Extract text between two curly braces in a nested structure with Python使用 Python 提取嵌套结构中两个大括号之间的文本
【发布时间】:2019-06-14 01:44:50
【问题描述】:

作为为飞行模拟器创建“任务生成器”的第一步,我希望能够提取任务模板的片段,以便我可以更改或删除一些内容,将其重新组合在一起,然后生成一个新的“任务”文件。 我的 Python 技能很少。我不需要一个可行的解决方案,但想要一个进一步调查的方向。这是挑战:

这是输入文件的(简化)示例:

test_str = ("Group\n"
    "{\n"
    "   Name = \"Group 1\";\n"
    "   Index = 2;\n"
    "   Desc = \"Description\";\n"
    "   Block\n"
    "   {\n"
    "       Name = \"Block 1\";\n"
    "       Index = 497;\n"
    "       XPos = 171568.472;\n"
    "       YPos = 0.000;\n"
    "       ZPos = 204878.718;\n"
    "   }\n"
    "\n"
    "   Block\n"
    "   {\n"
    "       Name = \"Block 2\";\n"
    "       Index = 321;\n"
    "       XPos = 162268.472;\n"
    "       YPos = 0.000;\n"
    "       ZPos = 203478.718;\n"
    "   }\n"
    "\n"
    "}\n"
    "\n"
    "Group\n"
    "{\n"
    "   Name = \"Group 2\";\n"
    "   Index = 5;\n"
    "   Desc = \"Description\";\n"
    "   Block\n"
    "   {\n"
    "       Name = \"Block 3\";\n"
    "       Index = 112;\n"
    "       XPos = 122268.472;\n"
    "       YPos = 0.000;\n"
    "       ZPos = 208878.718;\n"
    "   }\n"
    "\n"
    "   Block\n"
    "   {\n"
    "       Name = \"Block 4\";\n"
    "       Index = 214;\n"
    "       XPos = 159868.472;\n"
    "       YPos = 0.000;\n"
    "       ZPos = 202678.718;\n"
    "   }\n"
    "\n"
    "}\n")

如您所见,该文件由许多可以分组的对象(“块”)组成。这是一个嵌套结构,因为组也可以分组(此处未显示)。 如何根据名称隔离一个特定组?

假设我只想在输出文件中使用“Group 2”,我希望得到结果:

Group
{
   Name = "Group 2";
   Index = 5;
   Desc = "Description";
   Block
   {
       Name = "Block 3";
       Index = 112;
       XPos = 122268.472;
       YPos = 0.000;
       ZPos = 208878.718;
   }

   Block
   {
       Name = "Block 4";
       Index = 214;
       XPos = 159868.472;
       YPos = 0.000;
       ZPos = 202678.718;
   }

}

对于组内的给定块,还有一个类似的问题。

【问题讨论】:

标签: python


【解决方案1】:

我发现以下内容可以正常工作,因为它将根据其名称返回正确的组。不是很通用,但现在可以使用:)。它基本上计算“{}”组的数量,直到找到属于第一个的组(来自:https://stackoverflow.com/a/2780461/10940433):

def findGroup( mission, name ):
    start_group = mission.find("   Name = \""+name)
    mission ="Group\n{\n"+mission[start_group:len(mission)]
    if '{' in mission:
      match = mission.split('{',1)[1]
      open = 1
      for index in range(len(match)):
         if match[index] in '{}':
            open = (open + 1) if match[index] == '{' else (open - 1)
         if not open:
            return "Group\n{"+match[:index]+"}\n"

test_str = ("Group\n"
    "{\n"
    "   Name = \"Group 1\";\n"
    "   Index = 2;\n"
    "   Desc = \"Description\";\n"
    "   Block\n"
    "   {\n"
    "       Name = \"Block 1\";\n"
    "       Index = 497;\n"
    "       XPos = 171568.472;\n"
    "       YPos = 0.000;\n"
    "       ZPos = 204878.718;\n"
    "   }\n"
    "\n"
    "   Block\n"
    "   {\n"
    "       Name = \"Block 2\";\n"
    "       Index = 321;\n"
    "       XPos = 162268.472;\n"
    "       YPos = 0.000;\n"
    "       ZPos = 203478.718;\n"
    "   }\n"
    "\n"
    "}\n"
    "\n"
    "Group\n"
    "{\n"
    "   Name = \"Group 2\";\n"
    "   Index = 5;\n"
    "   Desc = \"Description\";\n"
    "   Block\n"
    "   {\n"
    "       Name = \"Block 3\";\n"
    "       Index = 112;\n"
    "       XPos = 122268.472;\n"
    "       YPos = 0.000;\n"
    "       ZPos = 208878.718;\n"
    "   }\n"
    "\n"
    "   Block\n"
    "   {\n"
    "       Name = \"Block 4\";\n"
    "       Index = 214;\n"
    "       XPos = 159868.472;\n"
    "       YPos = 0.000;\n"
    "       ZPos = 202678.718;\n"
    "   }\n"
    "\n"
    "}\n")


print (findGroup(test_str,"Group 2"))

【讨论】:

    【解决方案2】:

    我对python也很陌生,但我会尝试为你提出一个解决方案。我已将您的 test_str = ... 复制到一个 input.txt 文件并用 python 加载它,然后使用 read() 方法重新创建字符串。我相信您正在寻找的是 find() 方法,它返回您正在寻找的子字符串的确切位置(在这种情况下 - 组和块)。找到所需的组或块后,您可以使用字符串切片,就像我在 blockData = allData[iWantThisBlock:nextBlock] 行中使用的那样,仅将字符串的一部分存储到新变量中。下面的代码将从您的字符串中打印出块 1。您可以使用相同的方法从字符串中获取组、其他块或参数。我真的希望这至少对你有一点帮助:)

    import os
    
    os.chdir('D:\\')
    fileDir = 'D:\\input.txt'
    inputFile = open(fileDir, 'r')
    
    allData = inputFile.read()
    
    iWantThisBlock = allData.find('Block 1')
    nextBlock = allData.find('Block 2')
    
    blockData = allData[iWantThisBlock:nextBlock]
    
    print(blockData)
    

    【讨论】:

    • 使用 find() 方法你也可以搜索弯括号:)
    • 是的,这就是我要找的。但是块或组可以有任意名称,所以我不知道后续组的名称。在这个例子中,“Block 2”也可以是“Bridge 23”之类的。
    • 我建议在下一个块中搜索“名称”字符串。您可以使用 find() 方法并指定原始字符串的一部分以查找 { 即 allData.find('name', 100, 200) }。例如,您可以在 allData 字符串中找到所有索引都是 'name' 子字符串,然后根据这些索引进行切片。附:这样您也可以搜索大括号“{”和“}”。
    猜你喜欢
    • 2014-09-11
    • 1970-01-01
    • 2013-11-10
    • 1970-01-01
    • 1970-01-01
    • 2019-02-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多