Парсер для вывода из командной строки - PullRequest
1 голос
/ 12 января 2020

Я получаю вывод командной строки в следующем формате

server
3 threads started
1.1.1.1                 ONLINE at SUN
                        version: 1.2.3.4
                        en: net

1.1.1.2                 ONLINE at SUN
                        version: 1.2.3.5
                        en: net

1.1.1.3                 OFFLINE at SUN
                        version: 1.2.3.6
                        en: net

File: xys
high=600
low=70
name=lmn

Я хочу проанализированный вывод, например

l1 = [
  {
    "1.1.1.1": {
      "status": "ONLINE",
      "version": "1.2.3.4",
      "en": "net"
    },
    "1.1.1.2": {
      "status": "ONLINE",
      "version": "1.2.3.5",
      "en": "net"
    },
    "1.1.1.3": {
      "status": "OFFLINE",
      "version": "1.2.3.6",
      "en": "net"
    }
  }
]

l2 = {
  "File": "xys",
  "high": 600,
  "low": 70,
  "name": "lmn"
}

Я получаю все это в строке. Я разделил строку на \ n и создал список, а затем из ключевого слова «Файл» создал 2 списка основного списка. Затем проанализировал оба списка по отдельности.

index = [i for i in range(len(output)) if "File" in output[i] ]
if index:
    list1 = output[:index[0]]
    list2 = output[index[0]:]


Есть ли другой, более эффективный способ анализа этого вывода.

Ответы [ 2 ]

1 голос
/ 12 января 2020

В приведенном ниже решении не нужно использовать количество запущенных потоков сервера, поскольку оно может отслеживать номер потока, удаляя все метаданные, предшествующие и следующие за информацией о потоках:

with open("data.txt", "r") as inFile:
    lines = [line for line in inFile]
    lines = [line for line in lines[2:] if line != '\n']
    threads = lines[:-4]
    meta = lines[-4:]
    l1 = []
    l2 = {}
    for i in range(0,len(threads),3):
        status = threads[i]
        version = threads[i+1]
        en = threads[i+2]

        status = status.split()
        name = status[0]
        status = status[1]

        version = version.split()
        version = version[1].strip()

        en = en.split()
        en = en[1].strip()

        l1.append({name : {'status' : status, "version" : version, "en" : en}})

    fileInfo = meta[0].strip().split(": ")
    l2.update({fileInfo[0] : fileInfo[1]})

    for elem in meta[1:]:
        item = elem.strip().split("=")
        l2.update({item[0] : item[1]})

результат будет:

Для l1:

[{'1.1.1.1': {'status': 'ONLINE', 'version': '1.2.3.4', 'en': 'net'}}, {'1.1.1.2': {'status': 'ONLINE', 'version': '1.2.3.5', 'en': 'net'}}, {'1.1.1.3': {'status': 'OFFLINE', 'version': '1.2.3.6', 'en': 'net'}}]

Для l2:

{'File': 'xys', 'high': '600', 'low': '70', 'name': 'lmn'}
1 голос
/ 12 января 2020

То, что вы сделали, сработало бы хорошо.

То, насколько вам следует беспокоиться об этом, будет зависеть от того, будет ли это просто быстрая настройка для нескольких автоматических тестов или этот код предназначен для службы в корпоративной среде, которая должна работать, но я бы беспокоился о том, что произойдет, если File: ... больше не будет строкой, следующей за IP-адресами. Если вы хотите убедиться, что это не выдает ваш код, вы можете go через строку строка за строкой его синтаксический анализ.

Вам понадобится ваш анализатор для проверки всех следующих случаев:

  • Сервер слова
  • Комментарии после сервера слова о том, сколько потоков было запущено
  • Любые другие комментарии после сервера слова
  • IP-адрес (regex - ваш друг)
  • Область с отступом, за которой следуют IP-адреса
  • пары значений ключей, разделенных двоеточием
  • пары значений ключей, разделенных знаком равенства

Но на самом деле, я думаю, то, что ты сделал, выглядит великолепно. Не так сложно изменить код с поиска «Файл» на что-то другое, если в этом когда-нибудь возникнет необходимость. Вы захотите потратить немного времени на проверку того, что «Файл» всегда обрабатывает IP-адреса. Если надежность очень важна, вам придется проделать дополнительную работу, чтобы защитить себя от возможных проблем в будущем, если порядок вещей изменится на вас.

...