You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Windows格式大型日志文件过滤需求及Perl代码故障求助

问题描述

需要对Windows格式的大型日志文件执行以下操作(不修改原文件):

  • 移除所有CRLF字符(即去掉\r)
  • 在日志末尾的CLG...与TRC...行之间插入空行
  • 以段落模式读取处理后的结果,若段落中包含特定Call-ID则打印对应段落,同时打印该段落中含rtpmap的行

但提供的Perl代码无法正常工作。

原Perl代码

use strict;
use warnings;

my $ID = "D5CCA1AE-686D11E2-A881ED01-8DFA6D70@10.218.16.2";
my $SDP;

open (LOG, "file.log") || die $!;

my $line;

while(<LOG>) {
        $line .= $_;
        $line =~s/\r//g;
}

local $/ = '';

while (<>) {
    if ( /Call-ID:\s+(.+)/ and $ID ) {
        $SDP = 1;
        print;        
        next;
    }

    print if $SDP && /\brtpmap\b/;

    $SDP = 0;
}

close(LOG);

日志示例

Jan 28 11:39:37.525 CET: //1393628/D5CC0586A87B/SIP/Msg/ccsipDisplayMsg:^M
Received:^M 
SIP/2.0 200 OK^M
Via: SIP/2.0/UDP 10.218.16.2:5060;branch=z9hG4bKB22001ED5^M
From: "Frankeerapparaat Secretariaat" <sip:089653717@10.210.2.49>;tag=E7E0EF64-192F^M
To: <sip:022046187@10.210.2.49>;tag=25079324~19cc0abf-61d9-407f-a138-96eaffee1467-27521338^M
Date: Mon, 28 Jan 2013 10:39:32 GMT^M
Call-ID: D5CCA1AE-686D11E2-A881ED01-8DFA6D70@10.218.16.2^M
CSeq: 102 INVITE^M
Allow: INVITE, OPTIONS, INFO, BYE, CANCEL, ACK, PRACK, UPDATE, REFER, SUBSCRIBE, NOTIFY^M
Allow-Events: presence^M
Supported: replaces^M
Supported: X-cisco-srtp-fallback^M
Supported: Geolocation^M
Session-Expires:  1800;refresher=uas^M
Require:  timer^M
P-Preferred-Identity: <sip:022046187@10.210.2.49>^M
Remote-Party-ID: <sip:022046187@10.210.2.49>;party=called;screen=no;privacy=off^M
Contact: <sip:022046187@10.210.2.49:5060>^M
Content-Type: application/sdp^M
Content-Length: 209^M
^M
v=0^M
o=CiscoSystemsCCM-SIP 2000 1 IN IP4 10.210.2.49^M
s=SIP Call^M
c=IN IP4 10.210.2.1^M
t=0 0^M
m=audio 16844 RTP/AVP 8 101^M
a=rtpmap:8 PCMA/8000^M
a=ptime:20^M
a=rtpmap:101 telephone-event/8000^M
a=fmtp:101 0-15^M
^M
Jan 28 11:39:37.529 CET: //1393628/D5CC0586A87B/SIP/Msg/ccsipDisplayMsg:^M
Sent:^M
ACK sip:022046187@10.210.2.49:5060 SIP/2.0^M
Via: SIP/2.0/UDP 10.218.16.2:5060;branch=z9hG4bKB2247150A^M
From: "Frankeerapparaat Secretariaat" <sip:089653717@10.210.2.49>;tag=E7E0EF64-192F^M
To: <sip:022046187@10.210.2.49>;tag=25079324~19cc0abf-61d9-407f-a138-96eaffee1467-27521338^M
Date: Mon, 28 Jan 2013 10:39:36 GMT^M
Call-ID: D5CCA1AE-686D11E2-A881ED01-8DFA6D70@10.218.16.2^M
Max-Forwards: 70^M
CSeq: 102 ACK^M
Authorization: Digest username="Genk_AC_1",realm="infraxnet.be",uri="sip:022046187@10.210.2.49:5060",response="9546733290a96d1470cfe29a7500c488",nonce="5V/Jt8FHd5I8uaoahshiaUud8O6UujJJ",algorithm=MD5^M
Allow-Events: telephone-event^M
Content-Length: 0^M
^M
^M
Jan 28 11:39:37.529 CET: //1393627/D5CC0586A87B/SIP/Msg/ccsipDisplayMsg:^M
Sent:^M
SIP/2.0 200 OK^M
Via: SIP/2.0/UDP 192.168.8.11:5060;branch=z9hG4bK24ecaaaa6dbd3^M
From: "Frankeerapparaat Secretariaat" <sip:3717@192.168.8.11>;tag=e206cc93-1791-457a-aaac-1541296cf17c-29093746^M
To: <sip:022046187@192.168.8.28>;tag=E7E0F8A4-EA3^M
Date: Mon, 28 Jan 2013 10:39:32 GMT^M
Call-ID: fedc8f80-10615564-45df0-b08a8c0@192.168.8.11^M
CSeq: 101 INVITE^M
Allow: INVITE, OPTIONS, BYE, CANCEL, ACK, PRACK, UPDATE, REFER, SUBSCRIBE, NOTIFY, INFO, REGISTER^M
Allow-Events: telephone-event^M
Remote-Party-ID: <sip:022046187@192.168.8.28>;party=called;screen=no;privacy=off^M
Contact: <sip:022046187@192.168.8.28:5060>^M
Supported: replaces^M
Supported: sdp-anat^M
Server: Cisco-SIPGateway/IOS-15.3.1.T^M
Session-Expires:  1800;refresher=uas^M
Require: timer^M
Supported: timer^M
Content-Type: application/sdp^M
Content-Disposition: session;handling=required^M
Content-Length: 247^M
^M
v=0^M
o=CiscoSystemsSIP-GW-UserAgent 7276 9141 IN IP4 192.168.8.28^M
s=SIP Call^M
c=IN IP4 192.168.8.28^M
t=0 0^M
m=audio 30134 RTP/AVP 8 101^M
c=IN IP4 192.168.8.28^M
a=rtpmap:8 PCMA/8000^M
a=rtpmap:101 telephone-event/8000^M
a=fmtp:101 0-15^M
a=ptime:20^M
^M
CLG(2022-11-07 00:09:06.444)| Call(Terminate) | 302A330B040C73070A021806021C0200 | ^M
TRC(2022-11-15 00:00:38.012)| SIP( OUT : Response ) Trying( 100 INVITE ) | 2 |  | 0 | 332C30050A0F750A00011A06021C0200 | SIP/2.0 100 Trying^M
问题分析

原代码存在几个关键问题:

  1. 读取日志文件后将内容存入$line变量,但后续用while (<>)读取的是标准输入而非处理后的$line内容,逻辑完全错位。
  2. 段落模式的使用时机错误,未针对处理后的内容进行分割。
  3. 未实现CLG与TRC行之间插入空行的需求。
  4. 检查Call-ID的逻辑有误,and $ID仅判断变量非空,未匹配具体ID值。
修正后的代码
use strict;
use warnings;

my $target_id = "D5CCA1AE-686D11E2-A881ED01-8DFA6D70@10.218.16.2";

# 读取并处理文件内容
open my $log_fh, '<', 'file.log' or die "无法打开文件: $!";
local $/; # 一次性读取整个文件
my $content = <$log_fh>;
close $log_fh;

# 1. 移除所有CR字符(Windows格式的\r)
$content =~ s/\r//g;

# 2. 在CLG行和TRC行之间插入空行
$content =~ s/(CLG\(.*\).*)\n(TRC\(.*\).*)/$1\n\n$2/;

# 3. 按段落模式处理内容
local $/ = ''; # 段落模式:空白行分隔的块
# 将处理后的内容转为段落流
open my $processed_fh, '<', \$content or die "无法打开内存流: $!";

while (my $paragraph = <$processed_fh>) {
    # 检查段落是否包含目标Call-ID
    if ($paragraph =~ /Call-ID:\s+$target_id/) {
        print "=== 匹配到目标Call-ID的段落 ===\n";
        print $paragraph;
        
        # 提取并打印段落中的rtpmap行
        print "\n=== 段落中的rtpmap行 ===\n";
        print "$_\n" for ($paragraph =~ /^a=rtpmap:.+/mg);
        print "\n";
    }
}
close $processed_fh;
代码说明
  • 移除CR字符:用正则s/\r//g全局替换所有\r,将Windows格式转为Unix格式换行。
  • 插入空行:用正则匹配CLG开头的行和紧跟的TRC行,在中间插入一个空行。
  • 段落模式处理:通过内存文件句柄将处理后的内容按空白行分割为段落,逐个检查每个段落是否包含目标Call-ID:
    • 若匹配则打印整个段落。
    • 同时提取段落中所有a=rtpmap开头的行单独打印。
  • 改用词法文件句柄$log_fh替代旧式的LOG,更符合Perl现代编程规范。

内容的提问来源于stack exchange,提问作者shambhala

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.12 19:11:30