收到的SIP邀请的多行匹配是否有良好的正则表达式?

时间:2011-06-01 16:58:12

标签: python regex

我真的需要python regexp,它会给我这个信息:

数据:

  

收到1.1.1.1 18:41:51:330   (123字节):

     

邀请:sip:dsafsdf@fsdafas.com致:   sdfasdfasdfas
来自:“测试”   
途径:   sdafsdfasdfasd

     

从1.1.1.1 18:42:51:330发送   (123字节):

     

邀请:sip:dsafsdf@fsdafas.com
  来自:“测试”   
致:   sdfasdfasdfas
通过:   sdafsdfasdfasd

     

收到1.1.1.1 18:50:51:330   (123字节):

     

邀请:sip:dsafsdf@fsdafas.com
  通过:sdafsdfasdfasd
  来自:“测试”   
致:   sdfasdfasdfas

我需要实现的是找到“已接收”的最新INVITE以获取From:标头值。所以向后搜索数据。

独特的正则表达式是否可行? :)

感谢。

2 个答案:

答案 0 :(得分:2)

单行答案,假设您将整个标题插入带有嵌入换行符(或cr / nl)的字符串中:

sorted(re.findall("Received [^\r\n]+ (\d{2}:\d{2}:\d{2}:\d{3})[^\"]+From: \"([^\r\n]+)\"", data))[-1][1]

使用一个RE执行此操作的技巧是使用[^ \ r \ n]而不是。当你想扫描东西时。这可以假设从字符串始终具有双引号。双引号用于防止扫描仪在第一次接收时吞下整个字符串......;)

答案 1 :(得分:0)

我认为没有一个正则表达式是答案。我认为有条不紊的逐行匹配器就是你在这里寻找的。

import re
import collections

_msg_start_re = re.compile('^(Received|Sent)\s+from\s+(\S.*):\s*$')
_msg_field_re = re.compile('^([A-Za-z](?:(?:\w|-)+)):\s+(\S(?:.*\S)?)\s*$')
def message_parser():
    hdr = None
    fields = collections.defaultdict(list)
    msg = None
    while True:
        if msg is not None:
            line = (yield msg)
            msg = None
            hdr = None
            fields = collections.defaultdict(list)
        else:
            line = (yield None)
        if hdr is None:
            hdr_match = _msg_start_re.match(line)
            hdr = None if hdr_match is None else hdr_match.groups()
        elif len(fields) <= 0:
            field_match = _msg_field_re.match(line)
            if field_match is not None:
                fields[field_match.group(1)].append(field_match.group(2))
        else: # Waiting for the end of the message
            if line.strip() == '':
                msg = (hdr, dict(fields))
            else:
                field_match = _msg_field_re.match(line)
                fields[field_match.group(1)].append(field_match.group(2))

使用示例:

parser = msg_parser()
parser.next()
recvd_invites = [msg for msg in (parser.send(line) for line in linelst) \
                   if (msg is not None) and \
                      (msg[0][0] == 'Received') and \
                      ('INVITE' in msg[1])]

您可以使用多行正则表达式执行此操作,但如果您这样做,则可以将消息很好地解析为其各个字段。大概你想要对这些消息做一些有趣的事情,这样你就可以用它们做更多的事情,而不必使用更多的regexp。

这还允许您解析除现有文件之外的其他内容或包含其中所有消息的巨型字符串。例如,如果要解析在这些请求发生时打印出这些请求的管道的输出,则只需在每次收到一行时执行msg = parser.send(line)并在所有请求打印完成后立即获取新消息(如果该行不是消息的结尾,则msg将为None)。