【问题标题】:How to selectively ignore strings to in a python regex?如何在 python 正则表达式中选择性地忽略字符串?
【发布时间】:2017-01-30 02:28:40
【问题描述】:

我已经为我的路由器编写了一个相当基本的系统监视器来跟踪信号何时下降(以及当时发生的所有统计数据),因为非常出色的 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)

当我将它直接放入字典时,我想在找到时丢弃 Mbps 或 dB,但显然我所拥有的不会起作用。 如果我可以简单地从提取字段时得到的 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',

【问题讨论】:

  • 您能否提供示例输入和预期输出?
  • 嗨@niemmi - 为了清楚起见,刚刚添加了这一点
  • 您希望输出看起来像u'noise_up': u'6.50', u'conn_up': u'0.82', ...
  • obviously what I've got isn't going to work。不明显。这里的实际问题是什么?

标签: python beautifulsoup loggly


【解决方案1】:

您可以使用可选的非捕获组来匹配' 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

【讨论】:

  • 是的!这就是我正在寻找的语法!我无法弄清楚如何让它工作,因为每次我尝试它时它都没有匹配任何东西 - 所以假设它根本不会工作。非常感谢!
【解决方案2】:

尝试将您的模式更改为:

pattern = re.compile('(\w+)="\s*(.+?)\s*(?:Mbps|dB)?"')

如果我正确理解您想要什么,我认为这会起作用。它基本上就是您现在所拥有的,但是对于“Mbps/dB”有一个非捕获部分,因此这些单位不会包含在匹配中。

【讨论】:

  • 是的 - 我也想捕获链接状态,因为我要将滚动日志转储到保管箱以及 loggly 以便我可以有一些东西发送到我的电信公司,如果辍学率继续恶化
  • @Scott 哦,对不起!我完全错过了您试图为值捕获非数字数据的事实。我更新了我的答案,但似乎 niemmi 已经给了你想要的东西。祝你的项目好运。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-12-07
  • 1970-01-01
  • 2018-05-14
  • 1970-01-01
  • 1970-01-01
  • 2017-04-13
  • 1970-01-01
相关资源
最近更新 更多