Disposição de dados

0

Eu tenho dados que gostaria de obter saída no formato abaixo usando shell / perl script.

Dados:

Virtual Machine  Test status  Running.
Assigned Server  OVS001.local
Virtual Disk  Test_DISK1 (30) size  61GB
Physical Disk  HITACHI (110)
Physical Disk  HITACHI (113)
Physical Disk  HITACHI (111)

Saída exigida:

Virtual_Machine    Vdsks               size     Physical_Disks
Test               Test_DISK1          61GB        -
Test                 -                  -        HITACHI (110)
Test                 -                  -        HITACHI (113)
Test                 -                  -        HITACHI (111)

Isso precisa ser puxado para várias VMs ..

    
por biz 06.02.2016 / 22:47

2 respostas

0

perl foi projetado e criado exatamente para esse tipo de problema. Seu apelido era "lice de lixo eclético patológico".

Leia a documentação em perlform . O que você faz é ler seus dados (digamos, linha por vez), analisá-los, inserir variáveis e emitir o comando write , que gera os dados atuais com base em format que você definiu.

Para seus dados, você pode ter um formato para o cabeçalho:

format STDOUT_TOP = 
Virtual_Machine    Vdsks               size      Physical_Disks
-----------------  ------------------  --------- ---------------
.

e outro para cada linha de saída:

format STDOUT = 
@<<<<<<<<<<<<<<<<  @<<<<<<<<<<<<<<<<<  @>>>>>>>>>>> -
$virtualmachine,   @vdisk,             @vdisk_size
@<<<<<<<<<<<<<<<<  @<<<<<<<<<<<<<<<~~  @>>>>>>>>>~~ -
$#vdisk<0?'':$virtualmachine,   shift(@vdisk), shift(@vdisk_size)
@<<<<<<<<<<<<<<<<  -                                ^<<<<<<<<<<<<~~
$#disks<0?'':$virtualmachine,                       shift(@disks)

.

Não sei ao certo como você obtém seus dados, mas digamos que você os tenha em um arquivo separado por duas novas linhas. Cada host é um bloco de linhas:

Virtual Machine  Test1 status  Running.
Assigned Server  OVS001.local
Virtual Disk  Test_DISK1 (30) size  61GB
Physical Disk  HITACHI (110)
Physical Disk  HITACHI (113)
Physical Disk  HITACHI (111)

Virtual Machine  Test status  Running.
Assigned Server  OVS002.local
Virtual Disk  Test_DISK1 (30) size  41GB
Physical Disk  HITACHI (110)
Physical Disk  HITACHI (113)
Physical Disk  HITACHI (111)

Você define seu caractere delimitador de entrada assim:

$/="\n\n";

Toda vez que você lê, você está recebendo um bloco inteiro de texto, ou seja, todas as linhas de um host virtual.

while (<>) { 
    # process one virtual machine
}

Agora a diversão começa: analisando a entrada. Dentro do loop while, você pode fazer isso:

my @lines=split("\n");
local @disks=(); # initialize
local $virtualmachine="unknown";
local $physicalserver="unknown";
local @vdisk=("unknown");
local @vdisk_size=("unknown");
foreach (@lines) { 
    $virtualmachine = $1 if /^Virtual Machine\s+(\S+)\s+status\s+/;
    $physicalserver = $1 if /^Assigned Server\s+(\S+)/;
    do { push @vdisk,$1; push @vdisk_size,$2; }
       if /^Virtual Disk\s+(\S+).* size\s+(\d+\w+)/;
    push @disks,$1 if /^Physical Disk\s+(.*)/;
}
write;

A análise é bruta, mas geralmente eficaz.

    
por 07.02.2016 / 00:19
0

Depende da precisão com que você deseja a formatação - normalmente a tabulação separada é suficiente - mas eu lidaria com isso da seguinte forma:

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

#set record separator to double line feed.     
local $/ = "\n\n";

#print header row
print join "\t", "VM", "Virtual_Disk", "size", "Physical Disks", "\n";

#iterate stdin or files specified on command line
while ( <> ) { 
   #capture data from this 'chunk':
   my ( $vm ) = /Virtual Machine\s+(\w+)/;   
   my ( $status ) = /status\s*(\w+)/; 
   my @physical_disks = m/Physical Disk\s+(.*)/g; 
   my %virtual_disks = m/Virtual Disk\s+(\w+).*size\s+(\w+)/g;

   #output tab separated
   print join ("\t", $vm, $_, $virtual_disks{$_}, "-" ), "\n" for keys %virtual_disks;
   print join ("\t", $vm, "-", "-", $_ ), "\n" for @physical_disks;   
}

Isso se alinha a paradas de tabulação, em vez de largura fixa por si só. Isso pode ser mais adequado, dependendo do seu caso de uso. Caso contrário, você pode usar format como descrito acima ou sprintf para corrigir a largura do campo:

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

local $/ = "\n\n";
my $field_format = "%8s";  #string, 8 chars wide

print join "\t", map { sprintf $field_format, $_ } "VM", "Virtual_Disk", "size", "Physical Disks", "\n";

while ( <> ) { 
   my ( $vm ) = /Virtual Machine\s+(\w+)/;   
   my ( $status ) = /status\s*(\w+)/; 
   my @physical_disks = m/Physical Disk\s+(.*)/g; 
   my %virtual_disks = m/Virtual Disk\s+(\w+).*size\s+(\w+)/g;
   print join "\t", map { sprintf $field_format, $_} ( $vm, $_, $virtual_disks{$_}, "-" ), "\n" for keys %virtual_disks;
   print join "\t", map { sprintf $field_format, $_} ( $vm, "-", "-", $_ ), "\n" for @physical_disks;   
}
    
por 07.02.2016 / 14:37