Извлечение только json / dict из текста ИЛИ Получение текста внутри совпавших скобок - PullRequest
0 голосов
/ 17 апреля 2019

Я пытаюсь получить только часть json из большого текстового файла, который может содержать все виды текста ..

Я подошел к проблеме, пытаясь сопоставить / получить весь текст в скобках {}, ноТем не менее, я верю, что должен быть лучший способ сделать это, поэтому, пожалуйста, дайте мне предложение.Может быть, разбить файл и чем пытаться разобрать его, или мне не хватает какой-то библиотеки?Это я должен выполнить для файлов размером более 200 МБ.

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 голосов
/ 05 мая 2019

Поскольку вы используете Python, вы можете найти быстрый способ создания прототипа парсера для этого формата (который не является JSON, кстати): pyparsing:

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 выполняется не быстро и займет много времени, чтобы просмотреть ваш файл размером 200 МБ.

Pyparsing также плохо подходит для потоковой передачи, но он захочет проанализировать всю строку сразу. Это может или не может быть практичным с вашим файлом 200 МБ. Что вы можете сделать, это попробовать прочитать строку за раз, пока вы не получите анализируемую структуру, затем проанализировать ее и двигаться дальше. Или читайте 100 строк за раз, пока не получите анализируемую структуру, затем проанализируйте ее, оставьте неразобранную часть, а затем получите еще 100 строк. Но во всем этом ограничитель производительности будет синтаксическим анализатором, поэтому вы захотите свести к минимуму количество неправильных синтаксических анализов при попытке создать успешно разбираемую строку.

...