正则表达式捕获重复模式

时间:2017-09-12 23:30:58

标签: python regex regex-recursion

我一直在互联网上试图找出如何构建一个正则表达式以我需要的方式捕获文本;所以我看到了一些StackOverflow问题,但没有一个表达我想要的东西,但如果你已经在这里看到类似于我的问题的东西,pelase可以随意指向那篇文章......

我试图使用递归,但似乎我还不够好,无法让某些东西上班

一些注意事项:

1)我无法使用解析程序,因为使用此数据的程序将使用正则表达式来捕获它,并且该程序是一个通用的"实际上正在捕获任何所需数据的程序,我只需要提供正确的正则表达式来获取所需的信息,我也需要尽可能地保持它,因此我不能使用第三方或外部程序。

2)对'':'值'可以变化,它们并不总是相同数量的对...这就是我相信的难度。

3)将在Python 2.7.3中创建将使用此正则表达式的程序:    该程序如何工作:    它使用了一个Json配置文件,我可以设置我想要运行的命令,它会给我需要的数据,然后我指定一个正则表达式来教程序需要捕获什么以及如何处理它即:如何处理被捕获的组......这就是我无法使用解析器的原因。 该程序使用fabric将配置的收集器(带有正则表达式)运行到远程主机并收集所有数据......

4)程序用于收集数据以将其发布到网络服务器中并获取指标和其他内容,如图表和监控警报等

我已经能够捕获几乎所有我想要捕获的数据,但是当我试图为此创建一个收集器时,我就卡住了..

以下数据与下面的内容完全相同,但使用不同的服务器名称,当然值也会改变:

Server: Omega-X
celery.queue_length: {'transfer_data': '0', 'factor_a': '0', 'slow': '0', 'factor_b': '0', 'score_retry': '0', 'damage_factor_c': '0', 'voice_ud': '0', 'alarm_factors_bl': '0', 'telemetry_x': '0', 'endstream': '0', 'celery': '0', 'awl': '0', 'prs': '0', 'score': '0', 'feature_factors_xf': '0', 'feature_factors_dc': '0'}


Server: Alfa-X
celery.queue_length: {'transfer_data': '0', 'factor_a': '0', 'slow': '0', 'factor_b': '0', 'score_retry': '0', 'damage_factor_c': '0', 'voice_ud': '0', 'alarm_factors_bl': '0', 'telemetry_x': '0', 'endstream': '0', 'celery': '0', 'awl': '0', 'prs': '0', 'score': '0', 'feature_factors_xf': '0', 'feature_factors_dc': '0'}

我想如何捕获它:

Server: Omega-X

 transfer_data: 0
 factor_a: 0
 slow: 0
 factor_b: 0
 score_retry: 0
 damage_factor_c: 0
 voice_ud: 0
 alarm_factors_bl: 0
 telemetry_x: 0
 endstream: 0
 celery: 0
 awl: 0
 trx: 0
 points: 0
 feature_factors_xf: 0
 feature_factors_dc: 0

Server: Alfa-X

 transfer_data: 0
 factor_a: 0
 slow: 0
 factor_b: 0
 score_retry: 0
 damage_factor_c: 0
 voice_ud: 0
 alarm_factors_bl: 0
 telemetry_x: 0
 endstream: 0
 celery: 0
 awl: 0
 trx: 0
 points: 0
 feature_factors_xf: 0
 feature_factors_dc: 0

如果显示一个唯一的服务器,那么就不那么困难了,使用下面的正则表达式我能够捕获所有服务器(服务器名称除外):

'([a-z_]+)':\s'(\d+)'

这个正则表达式只会给出第二部分,它是变量和值的列表,但不是服务器名称...所以如果我在同一输出上输入几个具有相同数据的服务器,那么将无法从哪个服务器的值来自......

如果我尝试添加对服务器名称的支持: 我尝试过使用正则表达式,但它只能捕获服务器名称和第一对参数:

Server:\s([a-zA-Z0-9-]+)\s*celery\.queue_length:\s.('([a-z_]+)':\s'(\d+)')*

我尝试了多种递归功能,但我没能达到我想要的效果。

有人能指出我正确的方向吗??

感谢。

3 个答案:

答案 0 :(得分:1)

你想要键值吗?用python 我会用字典。

  1. 获取服务器名称和包含数据的字符串:
    Server: ([^\n]*)(?:[^{]*)\{(.*)\}

  2. 使用包含每个服务器数据的字符串构建一个dict:

  3. 使用python(你只需要import re语句):

    input = """Server: Omega-X
    celery.queue_length: {'transfer_data': '0', 'factor_a': '0', 'slow': '0', 'factor_b': '0', 'score_retry': '0', 'damage_factor_c': '0', 'voice_ud': '0', 'alarm_factors_bl': '0', 'telemetry_x': '0', 'endstream': '0', 'celery': '0', 'awl': '0', 'prs': '0', 'score': '0', 'feature_factors_xf': '0', 'feature_factors_dc': '0'}
    
    Server: Alfa-X
    celery.queue_length: {'transfer_data': '0', 'factor_a': '0', 'slow': '0', 'factor_b': '0', 'score_retry': '0', 'damage_factor_c': '0', 'voice_ud': '0', 'alarm_factors_bl': '0', 'telemetry_x': '0', 'endstream': '0', 'celery': '0', 'awl': '0', 'prs': '0', 'score': '0', 'feature_factors_xf': '0', 'feature_factors_dc': '0'}"""
    
    
    for match in re.findall(r'Server: ([^\n]*)(?:[^{]*)\{(.*)\}', input):
        server = match[0]
        data = match[1]
        datadict = dict((k.strip().replace("'", ""), v.strip().replace("'", "")) for k,v in (item.split(':') for item in data.split(',')))
        datadict['serveur'] = server
    

    然后您可以存储每个datadict(例如在列表中)并根据需要使用。您可以将值从字符串转换为整数以轻松操作它们。

答案 1 :(得分:0)

您可以使用Antlr来定义您的语法,并且比正则表达式更好:https://github.com/podsvirov/osgqtquick

如果你想使用正则表达式,你可以使用以下代码,请注意我的代码是在C#中,但正则表达式在Python中应该表现相同。

QQuickItem

说明:

+:一次或多次出现

\ w:字母数字

\ s:空格

[]:定义范围

(?< = a)b:正面观察,匹配b后面的

(?< = Server(\ s) :( \ s))\ s [\ w - ] +:匹配字母数字, - 和服务器后面的空格:

(?< = celery.queue_length [\ s:] * {)[a-zA-Z0-9 \ s:\' ,] +:匹配[a-zA的范围在celery.queue_length之后出现-Z0-9':, \ s]:

请注意,您需要添加"服务器:"服务器名称之前。这也不会从数据中删除单引号。

答案 2 :(得分:0)

感谢那些善意回答我问题的人,我想你们两个都帮助我重塑我看到这个问题......

我相信,我想要在这里实现的正则表达式非常困难:

给出了如何获取我想要的信息的难度。我在想以哪种方式更容易获得这些信息。所以我知道我在这里违反自己的规则,但我认为没有别的办法让我相信。

如果我想获得正则表达式组:

Server: Group 0
Key : Group 1
Value: Group 2

然后输出我需要的应该是:

Regex Groups:
        (0)      (1)          (2)         
Server: Omega-X transfer_data: 0
Server: Omega-X factor_a: 0
Server: Omega-X slow: 0
Server: Omega-X factor_b: 0
Server: Omega-X score_retry: 0
Server: Omega-X damage_factor_c: 0
Server: Omega-X voice_ud: 0
Server: Omega-X alarm_factors_bl: 0
Server: Omega-X telemetry_x: 0
Server: Omega-X endstream: 0
Server: Omega-X celery: 0
Server: Omega-X awl: 0
Server: Omega-X trx: 0
Server: Omega-X points: 0
Server: Omega-X feature_factors_xf: 0
Server: Omega-X feature_factors_dc: 0

通过这种方式,我可以使用非常简单的正则表达式处理同一输出中的任意数量的服务器...

"Server:\s([a-zA-Z_.-]+)\s'([a-zA-Z_]+)':\s'(\d+)'"

所以我认为最好的方法是添加Pre-Parser来准备这样的数据,然后处理它......

事实上,你们两个都对我有所帮助,非常感谢。

我想我会关闭这个问题,除非别人有更好的想法:)