【问题标题】:Greedy Quantifier problem with telnetlib's expect methodtelnetlib的expect方法的贪心量词问题
【发布时间】:2019-11-01 11:24:13
【问题描述】:

我正在尝试从具有大致这种格式的远程 Linux 机器捕获消息:

.*transmit message cmd: 0x1234, len: 20,
.*data: 00000000: 00 11 22 33 44 55 66 77 88 99 AA BB CC DD EE FF
.*data: 00000010: 00 11 22 33 
.*receive message cmd: 0x1234, len: 0,
.*transmit message cmd: 0x1234, len: 0,

我创建了一个正则表达式来捕获我想要的内容(一条消息,无论是发送还是接收消息),原则上是这样的:

 r'^.*(receive|transit).*message.*cmd(?P<cmd> [\da-fA-F]+,.*len(?P<len> \d+,(?:\n.*data:.*:.*)*'

带有 re.M 标志。

即找到任何包含“接收”或“传输”和“消息”的行,并且可能后面跟着 N 个“数据”行(假设 msg 的 len 不为 0),这就是最后一组可能出现的原因 > = 0。当针对文件中的数据运行(因此离线分析)时,此正则表达式完成其工作。但问题是,当此正则表达式应用于来自 Linux 机器的实时传入条纹时,众所周知,带有以贪婪量词结尾的正则表达式的 telnetlib.Telnet.expect() 的结果是不确定的:

如果正则表达式以贪婪匹配结尾(例如 .*)或者如果 多个表达式可以匹配相同的输入,结果是 不确定性,可能取决于 I/O 时序。

https://docs.python.org/2/library/telnetlib.html

如何重写正则表达式,使 telnetlib 的不足不被击中?我想不搜索“数据”,而是搜索与“接收”或“传输”不匹配的任何内容,因为这是新消息的开始。

【问题讨论】:

  • 更好的是:为传入的数据编写一个小型解析器。如果您需要帮助,请提供一些真实世界的输入以及您想要保留的内容。

标签: python regex


【解决方案1】:

您可以通过附加一个非贪婪指示符使* 匹配非贪婪,例如.*?

这里有一些关于贪婪与懒惰的解释:https://javascript.info/regexp-greedy-and-lazy

【讨论】:

  • 谢谢,我已经尝试过了,使用惰性变体它只匹配第一个数据行,就是这样。第二个和下一个不匹配(这是可以预料的,因为它们不贪婪)。问题是当在 expect() 方法中使用时,必须在正则表达式的末尾避免贪婪。当针对“实时”数据运行时,终点在哪里?对于文件,这很容易:过去和未来都在那里供检查。正如我在文件中指出的那样,正则表达式就像一个魅力。
  • 不,永远不会。模式末尾的.*? 总是匹配一个空字符串。此建议与建议在模式末尾删除 .* 相同。模式末尾的惰性量词总是匹配尽可能少的字符。
  • 也许我误解了 expect() 文档中的警告,但我更倾向于正则表达式能够以多种方式匹配,这会产生不确定的结果。对于非贪婪匹配,它总是会追求尽可能小的匹配,从而解决了流式传输问题
  • 我相信您需要知道最后有一个可以匹配的分隔符,例如输入结束或您关心的数据已经结束的指示。
  • 我们可以使用从消息头中捕获的“len”,它指示“数据”部分中有多少字节,因为每个“数据”最多携带 16 个字节,我们可以推断出 #要遵循的“数据”行。但这在我看来是一种矫枉过正的解决方案。
猜你喜欢
  • 2013-06-16
  • 1970-01-01
  • 1970-01-01
  • 2014-07-17
  • 1970-01-01
  • 2021-09-01
  • 2021-11-23
  • 2020-10-22
  • 1970-01-01
相关资源
最近更新 更多