ساعد في طباعة مفاتيح التجزئة إلى التنسيق المطلوب

StackOverflow https://stackoverflow.com/questions/3428868

سؤال

أحتاج إلى مساعدة في طباعة البيانات من Hash/Hash Ref إلى stdout أو ملف بالبيانات بترتيب محدد إن أمكن.

لديّ روتين بيرل يستخدم مراجع التجزئة مثل:

#!/usr/local/bin/perl 

use strict;
use warnings;
use File::Basename;
use Data::Dumper;
my %MyItems;

my $ARGV ="/var/logdir/server1.log";
my $mon = 'Aug';
my $day = '06';
my $year = '2010';

while (my $line = <>)
{
    chomp $line;
    if ($line =~ m/(.* $mon $day) \d{2}:\d{2}:\d{2} $year: ([^:]+):backup:/)
    {
        my $server = basename $ARGV, '.log';
        my $BckupDate="$1 $year";
        my $BckupSet =$2;

        $MyItems{$server}{$BckupSet}->{'MyLogdate'} = $BckupDate;
        $MyItems{$server}{$BckupSet}->{'MyDataset'} = $BckupSet;
        $MyItems{$server}{$BckupSet}->{'MyHost'} = $server;

        if ($line =~ m/(ERROR|backup-size|backup-time|backup-status)[:=](.+)/)
        {
            my $BckupKey=$1;
            my $BckupVal=$2;
            $MyItems{$server}{$BckupSet}->{$BckupKey} = $BckupVal;
        }
    }
}
foreach( values %MyItems ) {
     print "MyHost=>$_->{MyHost};MyLogdate=>$_->{MyLogdate};MyDataset=>$_->{MyDataset};'backup-time'=>$_->{'backup-time'};'backup-status'=>$_->{'backup-status'}\n";
}

الإخراج باستخدام Dumper:

$VAR1 = 'server1';
$VAR2 = {
          'abc1.mil.mad' => {
                                 'ERROR' => ' If you are sure  is not running, please remove the file and restart ',
                                 'MyLogdate' => 'Fri Aug 06 2010',
                                 'MyHost' => 'server1',
                                 'MyDataset' => 'abc1.mil.mad'
                               },
          'abc2.cfl.mil.mad' => {
                                  'backup-size' => '187.24 GB',
                                  'MyLogdate' => 'Fri Aug 06 2010',
                                  'MyHost' => 'server1',
                                  'backup-status' => 'Backup succeeded',
                                  'backup-time' => '01:54:27',
                                  'MyDataset' => 'abc2.cfl.mil.mad'
                                },

          'abc4.mad_lvm' => {
                                'backup-size' => '422.99 GB',
                                'MyLogdate' => 'Fri Aug 06 2010',
                                'MyHost' => 'server1',
                                'backup-status' => 'Backup succeeded',
                                'backup-time' => '04:48:50',
                                'MyDataset' => 'abc4.mad_lvm'
                              }
        };

تم تنسيق الإخراج الذي أود أن أرى:

MyHost=>server1;MyLogdate=>Fri Aug 06 2010;MyDataset=>abc2.cfl.mil.mad;backup-time=>Fri Aug 06 2010;backup-status=>Backup succeeded

فقط AddDed (8/7/2010): نموذج سجل السجل الخام أنا أستخدمه: (تمت إضافته مؤخرًا لتوفير تمثيل أفضل لسجل المصدر)

Fri Aug 06 00:00:05 2010: abc2.cfl.mil.mad:backup:INFO: backup-set=abc2.cfl.mil.mad
Fri Aug 06 00:00:05 2010: abc2.cfl.mil.mad:backup:INFO: backup-date=20100806000004

Fri Aug 06 00:48:54 2010: abc4.mad_lvm:backup:INFO: backup-size=422.99 GB
Fri Aug 06 00:48:54 2010: abc4.mad_lvm:backup:INFO: PHASE END: Calculating backup size & checksums
Fri Aug 06 00:48:54 2010: abc4.mad_lvm:backup:INFO: backup-time=04:48:50
Fri Aug 06 00:48:54 2010: abc4.mad_lvm:backup:INFO: backup-status=Backup succeeded
Fri Aug 06 00:48:54 2010: abc4.mad_lvm:backup:INFO: Backup succeeded
هل كانت مفيدة؟

المحلول 4

شكرا للجميع على الترويج في مساعدتهم ... هذا يعمل من أجلي.

  for my $Server(keys%MyItems){
    for my $BckupSet(keys%{$MyItems{$Server}}){
      for(sort keys%{$MyItems{$Server}{$BckupSet}}){
        print$_,'=>',$MyItems{$Server}{$BckupSet}{$_},';';
      }
      print"\n";
    }
  }

نصائح أخرى

لقد قضيت بعض الوقت في البحث عن الكود الخاص بك وأعتقد أنني قد اكتشفت ذلك.

والسبب في أن هذا كان من الصعب الإجابة عليه هو أنك زرعت عن غير قصد رنجة حمراء-إخراج Dumper Data.

لاحظ كيف يظهر $VAR1 = 'server1'; وثم $VAR2 = { blah };.

لقد دعت dumper مثل ذلك: print Dumper %MyItems;

المشكلة هي أن Dumper يريد قائمة من القيم لتفريغها ، نظرًا لأن قوائم Perl Flattens ، يجب تمرير الهياكل المعقدة بالرجوع إليها. لذا ، تحتاج إلى استدعاء Dumper مثل ذلك:

print Dumper \%MyItems;

هذا يدل على الهيكل كله.

عندما تسمى Dumper في وقت سابق ، قمت بتجريد طبقة واحدة من بنية البيانات عن غير قصد. تعمل الحلول المقترحة ، والرمز الخاص بك على هذا الهيكل الجذاب.

لقد قمت هنا بالانسحاب على بعض التعليمات البرمجية للتعامل مع طبقة إضافية من التعشيش (وجعلتها بيرل 5.8 متوافقة):

for my $server_items ( values %MyItems ) {
    for my $record ( values %$server_items ) {

        print join ';', map { 
            # Replace non-existant values with 'undef'
            my $val = exists $record->{$_} ? $record->{$_} : 'undef';

            "'$_'=>$val"  # <-- this is what we print for each field

        } qw( MyHost MyLogdate MyDataset backup-time backup-status );

        print "\n";
    }
}

يبدو أن لديك الكثير من الأسئلة وتحتاج إلى بعض المساعدة في الحصول على عدد من المفاهيم. أقترح عليك نشر طلب على PerlMonks في الباحثين عن حكمة Perl للمساعدة في تحسين الكود الخاص بك. لذلك من الرائع للسؤال المركز ، لكن PM أكثر قابلية لإعادة صياغة التعليمات البرمجية.

** الإجابة الأصلية: **

للتغلب على أي مشكلات تحليل لا يمكنني تكرارها ، لقد حددت للتو %MyItems إلى إخراج Dumper الذي قدمته.

تحذيراتك التي ذكرتها أعلاه لها علاقة بكل ما هو معقد والترميز المتكرر لديك في بيان الطباعة الخاص بك. لقد استبدلت بيان الطباعة الخاص بك بـ map لتبسيط الكود.

الهراء المقدس ، خريطة انضمام كبيرة بلاه ليس أبسط ، قد تفكر. ولكن في الحقيقة ، يكون الأمر أكثر بساطة لأن كل وحدة تعبير فردية أصغر. ما هو الأسهل للفهم والحصول على الصواب؟ ما هو الأسهل للتغيير والصيانة في مانور صحيح ومتسق؟

print "'foo'=>$_->{foo};'bar'=>$_->{bar};boo'=>$_->{boo};'far'=>$_->{far}\n";

أو

say join ';', map {
    "'$_'=>$item->{$_}"
} qw( foo bar boo far );

هنا ، يمكنك إضافة أو إعادة ترتيب الإخراج الخاص بك بمجرد تغيير قائمة الوسائط التي تم تمريرها إلى map. مع النمط الآخر ، لديك مجموعة من النسخ/لصق للقيام به.

الخريطة التي أستخدمها أدناه أكثر تعقيدًا قليلاً ، حيث تتحقق لمعرفة ما إذا كان يتم تعريف مفتاح معين قبل طباعة قيمة ، وتعيين قيمة افتراضية في حالة وجود أي منها.

#!perl

use strict;
use warnings;

use feature 'say';

my %MyItems = (
    'abc1.mil.mad' => {
        'ERROR' => ' If you are sure  is not running, please remove the file and restart ',
        'MyLogdate' => 'Fri Aug 06 2010',
        'MyHost' => 'server1',
        'MyDataset' => 'abc1.mil.mad'
    },

    'abc2.cfl.mil.mad' => {
        'backup-size' => '187.24 GB',
        'MyLogdate' => 'Fri Aug 06 2010',
        'MyHost' => 'server1',
        'backup-status' => 'Backup succeeded',
        'backup-time' => '01:54:27',
        'MyDataset' => 'abc2.cfl.mil.mad'
    },

    'abc3.mil.mad' => {
        'backup-size' => '46.07 GB',
        'MyLogdate' => 'Fri Aug 06 2010',
        'MyHost' => 'server1',
        'backup-status' => 'Backup succeeded',
        'backup-time' => '00:41:06',
        'MyDataset' => 'abc3.mil.mad'
    },

    'abc4.mad_lvm' => {
        'backup-size' => '422.99 GB',
        'MyLogdate' => 'Fri Aug 06 2010',
        'MyHost' => 'server1',
        'backup-status' => 'Backup succeeded',
        'backup-time' => '04:48:50',
        'MyDataset' => 'abc4.mad_lvm'
    }
);


for my $record ( values %MyItems ) {

    say join ';', map { 
        my $val = $record->{$_} // 'undef';  # defined-or requires perl 5.10 or newer.

        "'$_'=>$val"  # <-- this is what we print for each field

    } qw( MyHost MyLogdate MyDataset backup-time backup-status );

}

لم يتم اختباره ولكن يجب أن يعمل من الناحية النظرية. سيؤدي ذلك إلى طباعة خط الإخراج لكل من مفاتيح تجزئة MyItems الرئيسية. إذا كنت تريد كل شيء على سطر واحد ، يمكنك فقط إسقاط n أو إضافة بعض الفاصل الآخر.

foreach( values %MyItems ) {
     print "MyServer=>$_->{MyServer};MyLogdate=>$_->{MyLogdate};MyDataset=>$_->{MyDataset};backup-time=>$_->{backup-time};backup-status=>$_->{backup-status}\n";
}

عدم الإجابة على السؤال الذي طرحته ، لكن هذا لا يبدو منطقيًا بالنسبة لي.

تريد مجموعة من التجزئة وليس تجزئة.

لم يتم طلب التجزئة ، إذا كنت تريد طلبها ، فاستخدم صفيفًا.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top