Python正则表达式捕获跨越多行的多个匹配项

时间:2018-09-06 04:44:51

标签: python regex

我正在尝试提取使用python re跨越多行的adb输出的数据块。

示例数据为:

* ReceiverList{ac5847f 494 system/1000/u-1 local:ecc819e}
app=494:system/1000 pid=494 uid=1000 user=-1
Filter #0: BroadcastFilter{db24c4c}
Action: "android.app.action.DEVICE_POLICY_MANAGER_STATE_CHANGED"
Action: "android.intent.action.USER_PRESENT"
Action: "android.intent.action.USER_ADDED"
Action: "android.intent.action.USER_REMOVED"
AutoVerify=false
* ReceiverList{d0a75c1 494 system/1000/u-1 local:22946a8}
app=494:system/1000 pid=494 uid=1000 user=-1
Filter #0: BroadcastFilter{19b2166}
Action: "android.intent.action.USER_ADDED"
Action: "android.intent.action.USER_REMOVED"
AutoVerify=false
Filter #1: BroadcastFilter{e1e7ca7}
Action: "android.intent.action.PACKAGE_ADDED"
Action: "android.intent.action.PACKAGE_REMOVED"
Scheme: "package"
AutoVerify=false
* ReceiverList{4b668d3 691 com.android.systemui/10016/u0 remote:523b2c2}
app=691:com.android.systemui/u0a16 pid=691 uid=10016 user=0
Filter #0: BroadcastFilter{bcd1c10}
Action: "android.media.VOLUME_CHANGED_ACTION"
Action: "android.media.STREAM_DEVICES_CHANGED_ACTION"
Action: "android.media.RINGER_MODE_CHANGED"
Action: "android.media.INTERNAL_RINGER_MODE_CHANGED_ACTION"
Action: "android.media.STREAM_MUTE_CHANGED_ACTION"
Action: "android.os.action.ACTION_EFFECTS_SUPPRESSOR_CHANGED"
Action: "android.intent.action.CONFIGURATION_CHANGED"
Action: "android.intent.action.SCREEN_OFF"
Action: "android.intent.action.CLOSE_SYSTEM_DIALOGS"
AutoVerify=false
...

我试图提取以* ReceiverList...开始并以最后AutoVerify=false结尾的每组数据。一些数据集有多个AutoVerify=false。最终输出应反映[*ReceiverList...AutoVerify... , *ReceiverList...Autoverify...]

到目前为止,我尝试过的一些事情是:

  • re.findall(r'^\*.Receiver.+', data, flags=re.M)可以产生所需的效果,但第一行只显示一个。
  • re.findall(r'^\*.Receiver.+AutoVerify=\w+$', data, flags=re.M|re.DOTALL),这将捕获两组数据。
  • re.findall(r'^\*.Receiver.+(?=AutoVerify=\w+)', data, flags=re.M),这也不足够。

请注意,在示例数据集中,有两个AutoVerify=false。在第二组中,我想包括所有数据,直到下一个* ReceiverList开始为止。

2 个答案:

答案 0 :(得分:1)

使用split来分隔换行符,并提前查找\* ReceiverList

re.compile("\r?\n(?=\* ReceiverList)").split(s)

答案 1 :(得分:1)

您可以尝试以下模式:\* ReceiverList((?!\* ReceiverList)[\w\W])+AutoVerify=false

它将在字面上匹配边界:\* ReceiverListAutoVerify=false

这两者之间的所有内容都将与该模式((?!\* ReceiverList)[\w\W])+匹配,该模式表示:匹配[\w\W]之前没有出现的任何字符(\* ReceiverList)的一个或多个出现,因此不要跳过其他消息。

Demo

甚至更简单:\* ReceiverList((?!\* ReceiverList)[\w\W])+