1

这是我的输入文件

    ^A{1:IRVTUS30XXX}{2:I300dfaffaefa}{3:fewfa]}
    :15A:
    :20:1234556
    :22:dsafas
    dsafafaf
    erwfafgr
    :23:fewfd
    :24:firh
    :60:uncenjnjcdv
    :72:uenuernfk
    12345
    -}^C^A{1:IRVTUS30XXX}{2:I304dfaffaefa}{3:fewfa]}
    :15A:
    :20:1234556
    :22:dsafas
    dsafafaf
    erwfafgr
    :23:fewfd
    :24:firh
    :60:uncenjnjcdv
    :72:uenuernfk
    12345
    -}^C^A{1:IRVTUS30XXX}{2:I306dfaffaefa}{3:fewfa]}
    :15A:
    :20:1234556
    :22:dsafas
    dsafafaf
    erwfafgr
    :23:fewfd
    :24:firh
    :60:uncenjnjcdv
    :72:uenuernfk
    12345
    -}^C

在这里,我想使用以下命令删除几行。如果传入的消息是类型 300(取决于第一行 2:I300 中的这个标签),我只需要为 ^A 和 ^C 之间的消息执行第一个命令,其中模式 I305 应该在那里。对于 I304,我想执行第二个命令,而对于 I306,我应该执行第三个命令。

     1) perl -i -pe 's/:20:(.*)\r\n//g' (for Type 300)
     2) perl -i -pe 's/:22:(.*)\r\n//g' (for Type 305)
     3) perl -i -pe 's/:(15A|15B):(.*)\r\n//g' (for Type 306)

不知何故,我需要逐条消息地读取文件,即以 ^A 开头并以 ^C 结尾

请注意,我需要使用 perl 命令进行就地替换,而不是创建任何临时文件,因为我想在文件中保留的特殊字符很少。

4

1 回答 1

5

这是一种荒谬的文件格式,但仍然可以解析。

如果每个部分都以 结尾^C,我们可以将其用作记录分隔 $/符,默认为换行符:

use strict; use warnings;

local $/ = "-}\x03";  # ^C
while (<>) {
  chomp;
  ...;
}

现在在该循环中,我们解析输入,例如:

# parse headers
s/\A\x01// or die "Section must start with ^A";
my ($headers, @lines) = split /\n\K/;  # \Keep the newline
my %headers = $headers =~ /\G\{ ([0-9]+) : ([^\}]+) \}/xg;

# extract the type:
$headers{2} =~ /\AI([0-9]{3})/ or die "Couldn't extract type";
my $type = $1;

# depending on the type, select a filter that matches forbidden lines
my $filter = {
  300 => qr/\A:20:/,
  305 => qr/\A:22:/,
  306 => qr/\A:15[AB]:/,
}->{$type};
$filter //= qr/(*FAIL)/; # matches never

print $headers;
# print out all lines that don't match this filter:
print for grep !/$filter/, @lines;
print "-}\x03";

此代码未经测试,但您应该能够适应它。

于 2013-10-17T21:02:52.127 回答