Perl:编辑日志文件数据

如何解决Perl:编辑日志文件数据

我有一个像这样(以下)的表结构形式的日志文件,并想在其中编辑相同的send-id列。我刚接触perl并尝试过,但无法获得想要的东西。

Code   send_id   dest_id
AW      96       45
BX      65       96

现在在这里,我必须将send_id列ID修改为名称(例如96 = Alex和65 = James)并重新生成日志文件,如下所示格式[在此处输入图像描述] [2]。

Code  send_id  dest_id
AW     Alex     45
BX     James    96

我一直到这里都没有得到想要的输出,我正在逐行阅读。 我越来越像这样

Code  send_id  dest_id
AW     Alex     45
James

谁能告诉我该怎么做?

谢谢。

#!/usr/bin/perl

use warnings;
use strict;

my $log_file = "/home/ajay/Desktop/log.log";
open(Log1,"<$log_file") or die ("Could not open");
open(Log2,">$log2.pl");
while ($a=<Log1>) {
  if ($a =~ /65/){
    $a = "James";
    print Log2"$a\n";
  }
  else {
    print Log2"$a";
  }
}
close Log2;
close Log1;

解决方法

您可以使用以下方法在当前行中替换替换值:

while (my $line = <$Log1>) {
    chomp $line;
    if ($line =~ /65/){
        $line =~ s/65/James/;
    }
    say $Log2 $line;
}

但是,更好的方法是保留不同替换值的哈希值。例如这样的

use 5.22.0;
use strict;
use warnings;
use experimental qw(refaliasing);

my $log_file = "/home/ajay/Desktop/log.log";
my $log2_file = "/home/ajay/Desktop/log2.log";
open( my $Log1,"<",$log_file ) or die "Could not open file $log_file: $!";
open ( my $Log2,">",$log2_file) or die "Could not open file $log2_file: $!";
while (my $line = <$Log1>) {
    my @fields = split " ",$line;
    next if @fields != 3;
    \my $id = \$fields[1];
    if ( exists $id_map{$id} ) {
        $id = $id_map{$id};
    }
    say $Log2 (join "\t",@fields);
}
close $Log2;
close $Log1;

更新

要使输出字段居中,您可以尝试:

my %id_map = ("65" => "James","96" => "Alex");
open( my $Log1,$log_file ) or die "Could not open file $log_file: $!";
my $field_width = 20;
my $num_fields = 3;
open ( my $Log2,$log2_file) or die "Could not open file $log2_file: $!";
my $sep_line = ("-" x ($num_fields * $field_width));
while (my $line = <$Log1>) {
    my @fields = split " ",$line;
    next if @fields != $num_fields;
    \my $id = \$fields[1];
    if ( exists $id_map{$id} ) {
        $id = $id_map{$id};
    }
    say $Log2 $sep_line if $. == 1;
    say $Log2 (join " ",map {align($_,$field_width)} @fields);
    say $Log2 $sep_line if $. == 1;
}
close $Log2;
close $Log1;

sub align {
    my ( $str,$field_width ) = @_;

    my $len = length $str;
    if ($len >= $field_width) {
        return $str;
    }
    else {
        my $left = int(($field_width - $len) / 2);
        my $right = $field_width - $left - $len;
        my $str = (" " x $left) . $str . ( " " x $right );
        return $str;
    }
}

输出

------------------------------------------------------------
        Code               send_id              dest_id       
------------------------------------------------------------
         AW                  Alex                  45         
         BX                 James                  96         
,

您不太清楚文件的格式。看起来可能用制表符分隔,所以这就是我要处理的方式。如果不是这种情况,则需要对该代码进行一些小的调整。

我也摆脱了所有文件处理代码。该任务应作为Unix过滤器实现-即,它从STDIN读取并写入STDOUT。这使您的代码既简单又灵活。

我也使它成为数据驱动的。将新的ID /名称组合添加到%id哈希很简单。

#!/usr/bin/perl

use strict;
use warnings;
use feature 'say';

my %id = (
  96 => 'Alex',65 => 'James',);

while (<>) {
  chomp;
  my @fields = split;
  if (exists $id{$fields[1]}) {
    $fields[1] = $id{$fields[1]};
    say join "\t",@fields;
  } else {
    say;
  }
}

由于它是Unix过滤器,因此可以使用I / O重定向来调用它。如果假设我们将这段代码放在一个名为edittracker的文件中,那么我们将这样称呼它:

$ edittracker < /home/ajay/Desktop/log.log > log2.log

有关Unix过滤器模型的更多信息,请参见this article

,

您似乎具有固定的列格式。在这种情况下,unpack通常很方便将列分开。使用A格式说明符和列宽。

有了这些列后,只需查看您关心的列并随意替换其值即可。使用相同的格式将它们与pack放在一起:

use v5.10;

my $header = <DATA>;
print $header;

my %Replacements = (
    96 => 'Alex',);

my $format = 'A8 A9 A9';
while( <DATA> ) {
    chomp;
    my( $code,$send_id,$dest_id ) = unpack $format;

    $send_id = $Replacements{$send_id} // $send_id;
    say pack $format,$code,$dest_id
    }


__END__
Code   send_id   dest_id
AW      96       45
BX      65       96

请注意,这样的打包将截断大于宽度的数据。这是输出:

Code   send_id   dest_id
AW      Alex     45
BX      James    96
,

以下代码演示了许多可能的解决方案之一。

算法

  • id name对的文件读入哈希
  • 读取日志文件并将字段拆分为哈希
  • 用名称替换ID
  • 输出更新的数据
use strict;
use warnings;
use feature 'say';

my %ids;

while( <DATA> ) {            # ids
    next if /^\s*\z/;
    last if /__DATA__/;
    my($id,$name) = split;
    $ids{$id} = $name;
}

while( <DATA> ) {            # log file
    next if /^\s*\z/;
    chomp;
    if( /Code/ ) {
        say join("\t",split);
    } else {
        my %data;
        @data{qw/code send_id dest_id/} = split;
        $data{send_id} = $ids{ $data{send_id} } || $data{send_id};
        $data{dest_id} = $ids{ $data{dest_id} } || $data{dest_id};
        say join("\t",@data{qw/code send_id dest_id/});
    }
}

__DATA__
96  Alex
65  James

__DATA__
Code   send_id   dest_id
AW      96       45
BX      65       96

输出

Code    send_id dest_id
AW      Alex    45
BX      James   Alex

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其他元素将获得点击?
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。)
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbcDriver发生异常。为什么?
这是用Java进行XML解析的最佳库。
Java的PriorityQueue的内置迭代器不会以任何特定顺序遍历数据结构。为什么?
如何在Java中聆听按键时移动图像。
Java“Program to an interface”。这是什么意思?
Java在半透明框架/面板/组件上重新绘画。
Java“ Class.forName()”和“ Class.forName()。newInstance()”之间有什么区别?
在此环境中不提供编译器。也许是在JRE而不是JDK上运行?
Java用相同的方法在一个类中实现两个接口。哪种接口方法被覆盖?
Java 什么是Runtime.getRuntime()。totalMemory()和freeMemory()?
java.library.path中的java.lang.UnsatisfiedLinkError否*****。dll
JavaFX“位置是必需的。” 即使在同一包装中
Java 导入两个具有相同名称的类。怎么处理?
Java 是否应该在HttpServletResponse.getOutputStream()/。getWriter()上调用.close()?
Java RegEx元字符(。)和普通点?