使用perl格式化日期并忽略带有特殊字符的记录

时间:2015-01-29 16:21:05

标签: perl

我有一个包含3个字段的输入文件,如图所示。我想根据应用程序对服务器进行分组。我对任何这些字符(花括号,空格,点)的应用程序都不感兴趣。日期应转换为dd-mmm-yyyy(2013年5月18日)格式。

在帮助下,我已经部分实现了我想要的输出形式但是在格式化日期方面失败了。

我非常感谢格式化日期方面的任何帮助,也感谢我从输出中删除了应用程序中包含特殊字符的记录。

输入:

Date                 Server        application
01/02/2013 00:00     abc123        perl_module_1
01/02/2013 00:00     abc123        oracle_patch_201
03/05/2014 00:00     abc123        Microsoft()_pa.1.tch_71 (2)
04/04/2015 00:00     xyz1          oracle_patch_201
02/12/2015 00:00     xyz1          Cygwin_app
03/11/2013 00:00     lpr567        perl_module_1

输出:

ABL "TEST:perl_module_1" /UPDATE=(server[("abc123","lpr567"),("01-FEB-2013 00:00","03-NOV-2013 00:00")])
ABL "TEST:oracle_patch_201" /UPDATE=(server[("abc123","xyz1"),("03-MAY-2014 00:00","04-APR-2015 00:00")])
ABL "TEST:Cygwin_app" /UPDATE=(server[("xyz1"),("02-DEC-2015 00:00")])

这是我到目前为止所尝试的内容。

#!usr/bin/perl
use strict;
use warnings;

my $file = 'input.txt';
open my $info, $file or die "could not open $file: $!";
open(my $fh, '>', 'output.cmd');
my $application_string;
my $date_string;
my $oracledate;
my %applications_on;
my %servers_on;
my %date_on;

while ( <$info> ) {
   chomp;
   my ( $date, $time, $server, $application ) = split; 
   my %month_name;
   @month_name{ 0 .. 11 } = qw(Jan Feb Mar Apr May Jun Jul Aug Sept Oct Nov Dec);
   my ( $day, $month, $year ) = split ('/', $date);
   $date = join " ", $day, $month_name{$month}, $year;
  # my @date_values = split ('/',$date);
  # my $date_values[1] =~ s/01/JAN/;
  # $date = ($date_values[0].'-'.$date_values[1].'-'.$date_values[2]);
   push ( @{ $servers_on{$application} }, '"'.$server.'"');
   push ( @{ $date_on{$application} }, '"'.$date.'"');
}

foreach my $application ( keys %servers_on, keys %date_on ) {
    my $server_string = join ( ",", @{ $servers_on{$application} } ) ; 
    my $date_string = join ( ",", @{ $date_on{$application} } );
    printf $fh "ABL \"TEST:$application\" /UPDATE=(server[($server_string),($date_string)])\n";
}
close $info;

2 个答案:

答案 0 :(得分:0)

使用特殊字符删除记录:

这实际上取决于您对&#34;特殊字符的定义。&#34;

while ( <$info> ) {
    chomp;
    next if /[ whatever characters you think are special ]/;

或者可能更好:

    next unless /^[ -~]+$/;

除非它只包含低ascii可打印字符,否则应跳过该行。

转换日期:

use Time::Piece
  ...
my $new_date = uc Time::Piece
                  ->strptime($date, '%m/%d/%Y')
                  ->strftime('%d-%b-%Y');

答案 1 :(得分:0)

让我们从日期开始。使用Time::Piece可帮助您翻译和格式化日期。使用标准的Perl模块将使您的工作更轻松。

您的文件是如何设置的?这些标签是分开的字段吗?如果是这样,您应该使用Text::ParseWords来帮助您解析文本文件。由于我不知道实际的格式,我会作弊。


这将向您展示如何使用Time::Piece来读取和格式化日期。它还向您展示了如何使用Perl正则表达式抛出第一行和任何带有特殊字符的应用程序/\W/表示不是字母,数字或下划线的任何字符。

我将你的线分成一个或多个空格的四个数据。 Time::Piece->strptime需要时间和格式并返回可用于进一步处理的日期对象。该格式使用%x个字符来表示各种日期和时间。 date的联机帮助页通常包含%x格式及其代表的内容。获得约会后,我会使用sprintf格式化日期。

我将所有这些放入哈希值,然后将 引用 推送到包含您感兴趣的所有数据的数组中。注意反斜杠%data语句中push的前面。这非常重要,或者我只是将六个字段推入我的`@lines。如果您之前没有使用过Perl引用,则应阅读tutorial。引用允许您创建复杂的数据结构。

#! /usr/bin/env perl
#

use strict;
use warnings;
use feature qw(say);
use Data::Dumper;
use Time::Piece;

my @lines;
while ( my $line = <DATA> ) {
    chomp $line;
    next if $line !~ /^\d/;         # Skip first line
    my ( $date, $time, $server, $application ) = split /\s+/, $line;
    next if $application =~ /\W+/;
    my $time_format = "%m/%d/%Y %H:%M";
    my $date_obj = Time::Piece->strptime( "$date $time", $time_format)
        or die qq(Invalid datetime format "$date $time".);
    my $formatted_date = sprintf "%02d-%s-%04d %02d:%02d",
        $date_obj->mday, $date_obj->month, $date_obj->year,
        $date_obj->hour, $date_obj->min;
    my %data = ( 
        date   => $formatted_date, 
        app    => $application, 
        server => $server, 
    );
    push @lines, \%data;
}
say Dumper \@lines;
__DATA__
Date                 Server        application
01/02/2013 00:00     abc123        perl_module_1
01/02/2013 00:00     abc123        oracle_patch_201
03/05/2014 00:00     abc123        Microsoft()_pa.1.tch_71 (2)
04/04/2015 00:00     xyz1          oracle_patch_201
02/12/2015 00:00     xyz1          Cygwin_app
03/11/2013 00:00     lpr567        perl_module_1

这将打印出来:

$VAR1 = [
          {
            'server' => 'abc123',
            'time' => '02-Jan-2013 00:00',
            'app' => 'perl_module_1'
          },
          {
            'app' => 'oracle_patch_201',
            'server' => 'abc123',
            'time' => '02-Jan-2013 00:00'
          },
          {
            'app' => 'oracle_patch_201',
            'server' => 'xyz1',
            'time' => '04-Apr-2015 00:00'
          },
          {
            'app' => 'Cygwin_app',
            'server' => 'xyz1',
            'time' => '12-Feb-2015 00:00'
          },
          {
            'server' => 'lpr567',
            'time' => '11-Mar-2013 00:00',
            'app' => 'perl_module_1'
          }
        ];

从这里开始,你应该能够弄清楚如何获得你想要的输出。