从文本中仅提取json / dict或在匹配的括号内获取文本

时间:2019-04-17 16:22:14

标签: json python-3.x text-parsing python-textprocessing

我试图从大文本文件中仅获取json的一部分,该文件可以包含所有类型的文本。

我通过尝试匹配/获取括号{}之间的所有文本来解决问题,但是我仍然相信应该有更好的方法,所以请给我一些建议。也许是分割文件然后尝试解析文件,还是我缺少某些库?我必须对大于200MB的文件执行此操作。

citaj="""
..bla....bla....bla...bla....bla....
supportedBandCombination-r10{
  BandCombinationParameters-r10{
    BandParameters-r10{
      bandEUTRA-r101,
      bandParametersUL-r10{
        CA-MIMO-ParametersUL-r10{
          ca-BandwidthClassUL-r10a
        }
      },
      bandParametersDL-r10{
        CA-MIMO-ParametersDL-r10{
          ca-BandwidthClassDL-r10a,
          supportedMIMO-CapabilityDL-r10twoLayers
        }
      }
    }
  },
  BandCombinationParameters-r10{
    BandParameters-r10{
      bandEUTRA-r103,
      bandParametersUL-r10{
        CA-MIMO-ParametersUL-r10{
          ca-BandwidthClassUL-r10a
        }
      },
      bandParametersDL-r10{
        CA-MIMO-ParametersDL-r10{
          ca-BandwidthClassDL-r10a,
          supportedMIMO-CapabilityDL-r10twoLayers
        }
      }
    }
  }
}
..bla....bla....bla...bla....bla....
..bla....bla....bla...bla....bla...."""


import re
string = open("citaj.txt","r").read()
stack = 0
startIndex = None
results = []
indx = [m.start() for m in re.finditer('BandCombinationParameters', string)]
for jota in indx:
    for i, c in enumerate(string[jota:]):  
        if c == '{':
            if stack == 0:
                startIndex = i + 1 # string to extract starts one index later
            # push to stack
            stack += 1
        elif c == '}':
            # pop stack
            stack -= 1

            if stack == 0:
                results.append(string[startIndex:i])
print(results)

输出应为

results[0]=
BandCombinationParameters-r10{
  BandParameters-r10{
    bandEUTRA-r101,
    bandParametersUL-r10{
      CA-MIMO-ParametersUL-r10{
        ca-BandwidthClassUL-r10a
      }
    },
    bandParametersDL-r10{
      CA-MIMO-ParametersDL-r10{
        ca-BandwidthClassDL-r10a,
        supportedMIMO-CapabilityDL-r10twoLayers
      }
    }
  }
}
results[1]=
BandCombinationParameters-r10{
  BandParameters-r10{
    bandEUTRA-r103,
    bandParametersUL-r10{
      CA-MIMO-ParametersUL-r10{
        ca-BandwidthClassUL-r10a
      }
    },
    bandParametersDL-r10{
      CA-MIMO-ParametersDL-r10{
        ca-BandwidthClassDL-r10a,
        supportedMIMO-CapabilityDL-r10twoLayers
      }
    }
  }
}

1 个答案:

答案 0 :(得分:0)

由于您使用的是Python,因此您可能会发现pyparss为这种格式(不是JSON,btw)的解析器建立原型的快速方法:

src = """
supportedBandCombination-r10{
  BandCombinationParameters-r10{
    BandParameters-r10{
      bandEUTRA-r101,
      bandParametersUL-r10{
        CA-MIMO-ParametersUL-r10{
          ca-BandwidthClassUL-r10a
        }
      },
      bandParametersDL-r10{
        CA-MIMO-ParametersDL-r10{
          ca-BandwidthClassDL-r10a,
          supportedMIMO-CapabilityDL-r10twoLayers
        }
      }
    }
  },
  BandCombinationParameters-r10{
    BandParameters-r10{
      bandEUTRA-r103,
      bandParametersUL-r10{
        CA-MIMO-ParametersUL-r10{
          ca-BandwidthClassUL-r10a
        }
      },
      bandParametersDL-r10{
        CA-MIMO-ParametersDL-r10{
          ca-BandwidthClassDL-r10a,
          supportedMIMO-CapabilityDL-r10twoLayers
        }
      }
    }
  }
}"""

import pyparsing as pp

LBRACE,RBRACE = map(pp.Suppress, "{}")
term = pp.Word(pp.alphas, pp.alphanums+'-')

term_group = pp.Forward()
term_group <<= pp.Group(term + pp.Group(LBRACE 
                                         + pp.delimitedList(term_group | term) 
                                         + RBRACE))

term_group.parseString(src).pprint()

打印

[['supportedBandCombination-r10',
  [['BandCombinationParameters-r10',
    [['BandParameters-r10',
      ['bandEUTRA-r101',
       ['bandParametersUL-r10',
        [['CA-MIMO-ParametersUL-r10', ['ca-BandwidthClassUL-r10a']]]],
       ['bandParametersDL-r10',
        [['CA-MIMO-ParametersDL-r10',
          ['ca-BandwidthClassDL-r10a',
           'supportedMIMO-CapabilityDL-r10twoLayers']]]]]]]],
   ['BandCombinationParameters-r10',
    [['BandParameters-r10',
      ['bandEUTRA-r103',
       ['bandParametersUL-r10',
        [['CA-MIMO-ParametersUL-r10', ['ca-BandwidthClassUL-r10a']]]],
       ['bandParametersDL-r10',
        [['CA-MIMO-ParametersDL-r10',
          ['ca-BandwidthClassDL-r10a',
           'supportedMIMO-CapabilityDL-r10twoLayers']]]]]]]]]]]

但是,pyparsing的速度不是 快,并且要花很长时间才能筛选出200MB的文件。

Pyparsing对于流式处理也不是一件好事,但它想一次解析整个字符串。使用200MB文件可能不可行。您可以做的是尝试一次读取一行,直到获得一个可解析的结构,然后对其进行解析并继续前进。或者一次读取100行,直到获得可解析的结构,然后对其进行解析,保留未解析的部分,然后再获取100行。但是,在所有这些中,性能限制器将成为解析器,因此您将在尝试构建成功的可解析字符串的同时尽量减少不良解析的次数。