У меня есть следующий код на python, который содержит сообщения журнала для отладки SSH.
for log_item in ssh_log:
print(log_item.rstrip())
#will show ...
2022-04-06 01:55:15,085 10.x Remote version/idstring: SSH-2.0-ConfD-4.3.11.4
2022-04-06 01:55:15,085 20.x Connected (version 2.0, client ConfD-4.3.11.4)
2022-04-06 01:55:15,161 10.x kex algos:['diffie-hellman-group14-sha1'] server key:['ssh-rsa']
...
Каков подход, чтобы получить значения, выделенные жирным шрифтом, назначить мои переменные, возможно, какое-то регулярное выражение как часть цикла for или что-то еще, чтобы получить следующее:
idstring = SSH-2.0-ConfD-4.3.11.4
kex_algos = ['diffie-hellman-group14-sha1']
key_type = ['ssh-rsa']
Все ли строки в файле журнала содержат один из «Remote», «Connected» или «kex»? Предложенные до сих пор ответы могут работать для этого подмножества данных журнала, но что, если этих токенов нет в файле? Кроме того, почему вам нужны kex_algos и key_type в виде списков?
Привет, да, все линии будут иметь эти элементы. На самом деле мне не нужны kex_algos или key_type в виде списков, просто их вывод в журнале такой
Если все данные имеют тот же формат, что и данные, приведенные здесь, вы можете использовать следующее регулярное выражение:
import re
a = """
2022-04-06 01:55:15,085 10.x Remote version/idstring: SSH-2.0-ConfD-4.3.11.4
2022-04-06 01:55:15,085 20.x Connected (version 2.0, client ConfD-4.3.11.4)
2022-04-06 01:55:15,161 10.x kex algos:['diffie-hellman-group14-sha1'] server key:['ssh-rsa']"""
idstring = re.findall("idstring: (.*)", a)[0] # Remove zero to get a list if
# multiple values are present
print(idstring)
kex_algos = re.findall("algos:\['(.*)'\] ", a)
print(kex_algos)
key_type = re.findall("key:\['(.*)'\]", a)
print(key_type)
Выход:
'SSH-2.0-ConfD-4.3.11.4'
['diffie-hellman-group14-sha1']
['ssh-rsa']
Решение без регулярного выражения. См. встроенные комментарии ниже.
for log_item in ssh_log:
line = log_item.rstrip()
if 'idstring' in line:
print('idstring = ',line.split(':')[-1]) #Pick last value after ':'
if 'kex algos' in line:
print('kex algos = ', line[line.find('['):line.find(']')+1]) #find between first set of square brackets.
if 'key:' in line:
key = line.split('key:')[1] #Get values after 'key:'
print('key_type = ', key)
Вы можете обновить отпечатки для присвоения переменных, если это то, что вам нужно.
Вы также можете использовать шаблон ttp для анализа ваших данных, если ваши данные имеют аналогичную структуру.
from ttp import ttp
import json
with open("log.txt") as f:
data_to_parse = f.read()
ttp_template = """
{{ignore}} {{ignore}} {{ignore}} {{ignore}} version/idstring: {{version_id_string}}
{{ignore}} {{ignore}} {{ignore}} {{ignore}} algos:{{key_algos}} server key:{{key_type}}
"""
parser = ttp(data=data_to_parse, template=ttp_template)
parser.parse()
# print result in JSON format
results = parser.result(format='json')[0]
# print(results)
result = json.loads(results)
# print(result)
for i in result:
print(i["key_algos"])
print(i["key_type"])
print(i["version_id_string"])
Результат:
['diffie-hellman-group14-sha1']
['ssh-rsa']
SSH-2.0-ConfD-4.3.11.4
Имея 3 строки образца данных из исходного вопроса в файле, можно было бы использовать этот подход:
import re
with open('ssh.log') as sshlog:
for line in map(str.strip, sshlog):
_, _, _, kw, *rem = line.split()
match kw:
case 'Remote':
print(f'ID string = {rem[-1]}')
case 'kex':
m = re.findall("(?<=\[').+?(?='\])", line)
print(f'algos = {m[0]}')
print(f'type = {m[1]}')
case _:
pass
Здесь предполагается, что интерес представляют только строки с одним из ключевых слов «Remote» или «kex».
Выход:
ID string = SSH-2.0-ConfD-4.3.11.4
algos = diffie-hellman-group14-sha1
type = ssh-rsa
регулярное выражение может не понадобиться для такого простого случая. Вы можете просто использовать
log_item.find()
, чтобы отфильтровать соответствующие строки, затемlog_item.split()
, чтобы разделить их на строки и выбрать интересные по индексу.