Perl - مساعدة في التجزئة وإلقاء السجلات
-
30-09-2019 - |
سؤال
لديّ برنامج نصي بيرل يحتفظ فقط بمجموعة السجلات الأخيرة للمجموعة المسماة ولدي أكثر من مجموعة من السجلات. لذلك فإنه أكثر من كتابة البيانات في التجزئة والاحتفاظ بالمجموعة الأخيرة. أحتاج إلى مساعدة في طباعة جميع السجلات. شكرًا!
إليك نسخة من السيناريو الخاص بي:
#!/usr/local/bin/perl
use strict;
use warnings;
use Data::Dumper;
my ($ServerName)=@ARGV;
my %MyItems;
foreach my $ServerName(@ARGV){
while (my $line = <>){
chomp $line;
if ($line =~ m/.* \w+ \d{2} (\d{2}:\d{2}:\d{2}) \d{4}: ([^:]+):backup:/){
my $ServerName = basename $ARGV, '.mydomain.com.backup-software.log'; #$ARGV is reading input from command line
my $BckupSet =$2;
my $BckupVal=$1;
$MyItems{$ServerName}{$BckupSet}->{'1-Server'} = $ServerName;
$MyItems{$ServerName}{$BckupSet}->{'2-BackupSet'} = $BckupSet;
$MyItems{$ServerName}{$BckupSet}->{'3-StartTime'} = $BckupVal;
if ($line =~ m/(backup-date)[:=](.+)/){
my $BckupKey="4-DateStamp";
my $BckupVal=$2;
$MyItems{$ServerName}{$BckupSet}->{$BckupKey} = $BckupVal;
}
if ($line =~ m/(backup-time)[:=](.+)/){
my $BckupKey="5-Duration";
my $BckupVal=$2;
$MyItems{$ServerName}{$BckupSet}->{$BckupKey} = $BckupVal;
}
if ($line =~ m/(backup-size)[:=](.+)/){
my $BckupKey="6-Size";
my $BckupVal=$2;
$MyItems{$ServerName}{$BckupSet}->{$BckupKey} = $BckupVal;
}
if ($line =~ m/(Backup succeeded)/){
my $BckupKey="7-Status";
my $BckupVal="Succeeded";
$MyItems{$ServerName}{$BckupSet}->{$BckupKey} = $BckupVal;
}
if ($line =~ m/(ERROR)[:=](.+)/){
my $BckupKey="8-Status";
my $BckupVal="Unsuccessful";
$MyItems{$ServerName}{$BckupSet}->{$BckupKey} = $BckupVal;
print "$BckupKey=$BckupVal\n" if debug;
}
}
} #endwhile
print Dumper(\%MyItems);
for my $ServerName(keys%MyItems){
for my $BckupSet(keys%{$MyItems{$ServerName}}){
for(sort keys%{$MyItems{$ServerName}{$BckupSet}}){
#print$_,'=>',$MyItems{$ServerName}{$BckupSet}{$_},';';
print$_,'=',$MyItems{$ServerName}{$BckupSet}{$_},';';
}
print"\n";
}
}
} #END foreach
إليك ما يبدو عليه عندما يتفريغ:
$VAR1 = {
'server1.name.colo' => {
'set1' => {
'3-StartTime' => '07:08:15',
'1-Server' => 'server1.name.colo',
'6-Size' => '72.04 GB',
'7-Status' => 'Succeeded',
'4-DateStamp' => '20100820060002',
'5-Duration' => '01:08:13',
'2-BackupSet' => 'set1',
'8-Status' => 'Unsuccessful'
},
'set2' => {
'7-Status' => 'Succeeded',
'6-Size' => '187.24 GB',
'3-StartTime' => '01:51:25',
'4-DateStamp' => '20100820000003',
'1-Server' => 'server1.name.colo',
'5-Duration' => '01:51:21',
'2-BackupSet' => 'set2'
},
'set3' => {
'3-StartTime' => '23:00:05',
'4-DateStamp' => '20100814230003',
'1-Server' => 'server1.name.colo',
'8-Status' => 'Unsuccessful',
'2-BackupSet' => 'set3'
},
'set4' => {
'7-Status' => 'Succeeded',
'6-Size' => '427.75 GB',
'3-StartTime' => '00:43:20',
'4-DateStamp' => '20100819200004',
'1-Server' => 'server1.name.colo',
'5-Duration' => '04:43:14',
'2-BackupSet' => 'set4'
},
'set3' => {
'7-Status' => 'Succeeded',
'6-Size' => '46.42 GB',
'3-StartTime' => '04:42:59',
'4-DateStamp' => '20100820040002',
'1-Server' => 'server1.name.colo',
'5-Duration' => '00:42:56',
'2-BackupSet' => 'set3'
}
}
};
المحلول
بناءً على ناتج التصحيح ، يبدو أن مشكلتك موجودة هنا:
if ($line =~ m/(ERROR)[:=](.+)/){
my $BckupKey="8-Status";
my $BckupVal="Unsuccessful";
$MyItems{$ServerName}{$BckupSet}->{$BckupKey} = $BckupVal;
print "$BckupKey=$BckupVal\n" if debug;
}
لحفظ جميع الأخطاء ، ستحتاج إلى علاج فتحة التجزئة هذه كمرجع إلى صفيف:
if ($line =~ m/(ERROR)[:=](.+)/){
my $BckupKey="8-Status";
my $BckupVal="Unsuccessful";
push @{ $MyItems{$ServerName}{$BckupSet}{$BckupKey} } => $BckupVal;
print "$BckupKey=$BckupVal\n" if debug;
}
في تفريغك ، 8-Status
سوف تشبه القيم
'8-Status' => [ 'Unsuccessful', 'Other error', 'Et cetera' ],
إذا كنت ترغب في حلها في وقت لاحق ، فستفعل شيئًا مثل
foreach my $err (@{ $MyItems{$ServerName}{$BckupSet}{$BckupKey} }) {
print "got $err\n";
}
للحصول على الأول فقط ، كنت تكتب
print $MyItems{$ServerName}{$BckupSet}{$BckupKey}[0], "\n";
قضية أخرى هي
foreach my $ServerName(@ARGV){
while (my $line = <>){
ندرك ذلك while (<>) { ... }
حلقات ضمنية على جميع الملفات المسمى في @ARGV
, ، لذا تداخلها داخل حلقة @ARGV
لا معنى له. إذا كان سطر الأوامر الخاص بك من النموذج
$ readlogs server1 server2 server3 log1 log2
ثم تريد أولاً الإزالة من @ARGV
الخوادم باستخدام shift
. قد يكون التمييز بين الوسائط التي يعتزمها المستخدم كأسماء مضيف الخادم صعبة. اتفاقية واحدة تستخدم --
للإشارة إلى نهاية معالجة الخيار ، حتى تتمكن من ذلك
my @servers;
while (@ARGV) {
my $server = shift;
last if $server eq "--"
push @servers => $server;
}
die "Usage: $0 server .. -- log ..\n" unless @ARGV;
while (<>) {
# ...
}
نصائح أخرى
هذا خارج الموضوع ، ولكن في أي وقت تحتاج إلى هياكل بيانات متداخلة بعمق ، فإن الكود الخاص بك يخاطر بالانتفاخ ويصعب قراءته. تقطع متغيرات الراحة البسيطة شوطًا طويلاً نحو تبسيط الأشياء وتخفيف قارئ الكود (أنت ، بعد 3 أشهر من الآن) من الاضطرار إلى أداء العديد من الفرق العقلية:
# A convenience var.
my $bs = $MyItems{$ServerName}{$BckupSet};
# The rest of your code can use the var.
$bs->{'1-Server'} = $ServerName;
أيضا ، لديك عدة if
الكتل التي تفعل نفس الشيء بشكل أساسي. يبدو قابلاً لبعض استراتيجية جدول الإرسال:
my @dispatch_table = (
{
regex => qr/(backup-date)[:=](.+)/,
key => '4-DateStamp',
val => sub { $2 },
},
{
# etc.
},
);
ثم الخاص بك if
الكتل تغلي إلى شيء مثل هذا:
for my $dt (@dispatch_table){
next unless $line =~ $dt->{regex};
$bs->{ $dt->{key} } = $dt->{val}->();
}