【问题标题】:Extract multiple lines based on certain regex assertion condition根据某些正则表达式断言条件提取多行
【发布时间】:2019-07-24 18:07:55
【问题描述】:

我有一个很大的文本文件,我需要根据以下几行开头的特定条件提取某些数据块。如何使用 Python regex 包找到这些块并提取它们?

示例文件(source.txt)如下所示。

    .
    .
    .
    Request: 22:11:22
    Discription1: From the Client 1
    Discription2: requesting HTTP
    Version: 1.2
    Type: browsing
    Data: AAAA CFFFF FFF

    Answer: 33:22:44
    Discription1: From Server B
    Discription2: Respons HHTP
    Version: 1.1
    Type: browsing
    Data: kCmkc9AS 9as9 as99 as76d 8aS9d8 6ASDQWv sf

    Request: 31:24:53:33
    Discription1: From Client 2
       Discription2: requesting HTTP
        Version: 1.1

    Type: DASH
    Data: AAAA CFFFF FFF



    Answer: 41:24:33:33
    Discription1: From Server A
    Discription2: Response
    Version: 1.1
    Type: DASH
    Data:ask sef k5q3 WEB 54 fkl n5 qwe@#%@#SDG adkjwra;k4 kfk

    Request: 61:44:23:33
    Discription1: From Client 2
        Discription2: requesting HTTP

    Version: 1.1
       Type: DASH

    Data: AAAA CFFFF FFF
    Data Discription: From the Cleint VM2
    Answer: 71:25:33:33
      Discription1: From Server A
     Discription2: Response
        Version: 1.1
    Type: DASH

    Data:ask sef k5q3 WEB 54 fkl n5 qwe@#%@#SDG adkjwra;k4 kfk
    .
    .

我需要获取以“Request:”开头的块,其特征是:“version 1.1”和“Client 2”


重要提示

  1. 块的长度不同,所以它们不一样 信息,但它们具有相同的匹配特征。

  2. 它们之间有很多空格和换行符。

  3. 匹配的特征可能不完全出现在特定的行中 顺序。

  4. 我需要将这些块捕获到以下“Answer”关键字。**


预期的输出是:

 Request: 31:24:53:33
    Discription1: From Client 2
    Discription2: requesting HTTP
    Version: 1.1
    Type: DASH
    Data: AAAA CFFFF FFF

    Request: 61:44:23:33
    Discription1: From Client 2
    Discription2: requesting HTTP
    Version: 1.1
    Type: DASH
    Data: AAAA CFFFF FFF
    Data Discription: From the Cleint VM2

【问题讨论】:

  • 你需要比这更清楚。举个例子。
  • 该问题现已被删除(10k+ 用户可以看到它,但他们将无法评论或回答)。
  • 我已经更新了这个。

标签: python regex python-3.x regex-lookarounds regex-group


【解决方案1】:

您可以使用负前瞻来断言下一行的值:

^Message Request: .*(?:\r?\n(?!.* Client 2|Data:).*)*\r?\n.*Client 2.*(?:\r?\n(?!Version: 1\.1).*)*\r?\nVersion: 1\.1(?:\n(?!Data:).*)*\r?\nData: .*

说明

  • ^行首
  • Message Request: .* Match Message Request: 和其余的行
  • (?:\r?\n(?!.* Client 2|Data:).*)*只要该行不包含Client 2或以Data开头就匹配:
  • \r?\n.*Client 2.*匹配客户端2的行
  • (?:\r?\n(?!Version: 1\.1).*)* 只要行不包含版本 1.1 就匹配
  • \r?\nVersion: 1\.1匹配包含Version 1.1的行
  • (?:\n(?!Data:).*)*只要该行不以Data开头就匹配:
  • \r?\nData: .*匹配以Data开头的行:

Regex demo

例如使用re.M

import re
regex = r"^Message Request: .*(?:\r?\n(?!.* Client 2|Data:).*)*\r?\n.*Client 2.*(?:\r?\n(?!Version: 1\.1).*)*\r?\nVersion: 1\.1(?:\n(?!Data:).*)*\r?\nData: .*"

with open("source.txt", "r") as f:
    text1 = f.read()
print (re.findall(regex,text1, re.M))

结果

['Message Request: 31:24:53:33\nDiscription1: From Client 2\nDiscription2: requesting HTTP\nVersion: 1.1\nType: DASH\nData: AAAA CFFFF FFF', 'Message Request: 61:44:23:33\nDescription0:jdfj sdjd\nDiscription1: From Client 2\nDiscription2: requesting HTTP\nVersion: 1.1\nType: DASH\nData: AAAA CFFFF FFF']

【讨论】:

  • 我可以不使用否定断言吗?这是因为我有很多版本类型。另外,我可以不从 ^ 开始使用 serarch,因为这不在行的第一行。
  • 如果您能简化该模式,我将受到高度重视,因为它非常先进并且需要分解,至少对于我作为初学者而言。
  • 如果你愿意,你可以省略^,但是比赛也可以从另一个地方开始。您在问题中提到了version 1.1,所以我认为应该在模式中指定。负前瞻仅确保该行不包含该值。你说的不同类型是什么意思?它们会出现在哪里?
  • 我可以认为块的结尾是“消息答案:”而不是数据吗?这是因为请求块中的字段可能会有所不同,但唯一稳定的是条件。
  • 假设,例如,您有其他版本,例如1.2、1.0
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多