用于捕获重复模式的正则表达式

Regex Expression to capture repeated patterns

我一直在互联网上 运行探索如何构建正则表达式以我需要的方式捕获文本;所以我看到了一些 Whosebug 问题,但其中 none 表达了我想要的内容,但如果您已经在这里看到与我的问题类似的内容,请随时指点我那篇文章...

我尝试使用递归,但似乎我还不够好,无法让某些东西工作

一些注意事项:

1) 我不能使用解析程序,因为将使用此数据的程序将使用正则表达式来捕获它,而这个程序是一个 "general purpose" 程序,它实际上正在捕获任何数据是需要的,我唯一需要做的就是给出正确的正则表达式来获取它需要的信息,我还需要尽可能地保持一致,所以我不能使用第三方或外部程序。

2) 'key' 对:'value' 可能会有所不同,它们的对数并不总是相同的......这就是我认为困难的原因。

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

4) 程序用于收集数据 post 将它们放入网络服务器并获取指标和其他内容,例如图表和监控警报等

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

以下数据重复如下,但服务器名称不同,当然值也会发生变化:

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+)')*

我尝试了多种递归功能,但未能实现我想要的。

谁能给我指出正确的方向...?

谢谢。

您可以使用 Antlr 来定义语法,这将是比正则表达式更好的选择:https://dzone.com/articles/antlr-4-with-python-2-detailed-example

如果你想使用正则表达式,你可以使用下面的代码,请注意我的代码是在 C# 中,但正则表达式在 Python.

中应该表现相同
string serverNamePattern = @"(?<=Server(\s)*:(\s))\s*[\w-]+";
string dataPattern = @"(?<=celery.queue_length[\s:]*{)[a-zA-Z0-9\s:\'_,]+";
string 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'}";

var serverNames = Regex.Matches(input, serverNamePattern);
var dataMatches = Regex.Matches(input, dataPattern);

解释:

+:出现一次或多次

\w: 字母数字

\s: 白色 space

[]:定义一个范围

(?<=a)b: 正后视,匹配 a

之后的 b

(?<=Server(\s):(\s))\s[\w-]+:匹配字母数字,- 和白色 space在服务器之后:

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

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

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

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

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

与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

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

感谢好心回答我问题的人,我想你们都帮助我重塑了我看待这个问题的方式...

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

给出我想要的信息获取方式的难度。我在想用什么方式更容易让我得到这些信息。所以我知道我在这里违背了我自己的规则,但我认为我认为没有其他方法可以顺利进行。

如果我想获得像这样的正则表达式组:

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+)'"

所以我认为最好的方法是添加一个预解析器来准备这样的数据,然后对其进行处理...

事实上,你们都在这方面帮助了我,非常感谢。

我想我会关闭这个问题,除非有人提出更好的主意:)