3

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

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

一些注意事项:

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

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

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

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

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

谁能在这里指出我正确的方向...?

谢谢。

4

3 回答 3

1

你想要键值?使用 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

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

于 2017-09-13T08:16:50.537 回答
0

您可以使用 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:空白

[]:定义范围

(?<=a)b:正向向后看,匹配 a 之后的 b

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

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

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

于 2017-09-13T00:20:30.747 回答
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 来准备这样的数据,然后处理它......

事实上,你们俩都帮助我,非常感谢。

我想我会关闭这个问题,除非其他人是一个更好的主意:)

于 2017-09-13T12:16:01.327 回答