Как выборочно игнорировать строки в регулярном выражении Python?
Я написал довольно простой системный монитор для моего маршрутизатора, чтобы отслеживать, когда падает сигнал (и все статистические данные, которые произошли в то время), так как очень превосходный routerstatslite не собирает все, что мне нужно.
Вот суть, но я хочу очистить данные, прежде чем загружать их в loggly, чтобы при необходимости можно было удалить суффиксы db и mbps
https://gist.github.com/scottharman/6ca07a7c46ca09de3e3b2f0a5094d86e
script = stats.findAll('script')[1]
pattern = re.compile('(\w+)="(.*?)Mbps\|dB"')
fields = dict(re.findall(pattern, script.text))
clean_fields = { k:v.strip() for k, v in fields.iteritems()}
if old_fields != clean_fields:
logger.info(json.dumps(clean_fields))
old_fields = clean_fields
print clean_fields
sleep(5)
Поскольку я помещаю это прямо в диктат, я хочу отбросить Мбит / с или дБ, когда найден, но очевидно, что то, что у меня есть, не сработает. Будет проще, если я смогу просто удалить две строки из 70-80 нечетных строк состояния, которые я получил при извлечении полей, но разве это просто невозможно?
ура
Пример ввода из тега скрипта:
var conn_down=" 13.35 Mbps";
var conn_up=" 0.82 Mbps";
var line_down=" 34.60 dB";
var line_up=" 19.70 dB";
var noise_down=" 6.10 dB";
var noise_up=" 6.50 dB";
var sys_uptime="74523";
var lan_status="Link up";
var lan_txpkts="1294024";
var lan_rxpkts="2256747";
var lan_collisions="0";
var lan_txbs="10004";
var lan_rxbs="35259";
var lan_systime="74523";
Тогда обработанные данные выглядят так:
u'noise_up': u'6.50 dB', u'lan_rxbs': u'35259', u'an_rxpkts': u'2857867', u'bgn_status': u'600M', u'lan_status0': u'100M/Full',
u'lan_status3': u'1000M/Full', u'lan_status2': u'100M/Full', u'conn_up': u'0.82 Mbps',
2 ответа
Вы можете использовать необязательную группу без захвата, чтобы соответствовать ' Mbps'
или же ' dB'
:
import re
import pprint
s = '''var conn_down=" 13.35 Mbps";
var conn_up=" 0.82 Mbps";
var line_down=" 34.60 dB";
var line_up=" 19.70 dB";
var noise_down=" 6.10 dB";
var noise_up=" 6.50 dB";
var sys_uptime="74523";
var lan_status="Link up";
var lan_txpkts="1294024";
var lan_rxpkts="2256747";
var lan_collisions="0";
var lan_txbs="10004";
var lan_rxbs="35259";
var lan_systime="74523";'''
pattern = re.compile(r'(\w+)=\"\s*(.*?)(?:\sMbps|\sdB)?\"')
fields = dict(re.findall(pattern, s))
pprint.pprint(fields)
Выход:
{'conn_down': '13.35',
'conn_up': '0.82',
'lan_collisions': '0',
'lan_rxbs': '35259',
'lan_rxpkts': '2256747',
'lan_status': 'Link up',
'lan_systime': '74523',
'lan_txbs': '10004',
'lan_txpkts': '1294024',
'line_down': '34.60',
'line_up': '19.70',
'noise_down': '6.10',
'noise_up': '6.50',
'sys_uptime': '74523'}
В выше (\w+)=
захватывает один или несколько буквенно-цифровых символов, за которыми следует =
, \"\s*
соответствует кавычке, за которой следует ноль или более пробелов. (.*?)
не жадно захватывает любой текст и (?:\sMbps|\sdB)?
необязательная группа без захвата, которая соответствует ' Mbps'
или же ' dB'
, Смотрите regex101 demo.
Попробуйте изменить свой шаблон на:
pattern = re.compile('(\w+)="\s*(.+?)\s*(?:Mbps|dB)?"')
Я думаю, что это будет работать, если я правильно понимаю, что вы хотите. Это в основном то, что у вас есть сейчас, но с разделом без захвата для "Мбит / с / дБ", поэтому единицы не будут включены в матч.