データ構成

データ構成

シェル/パールスクリプトを使用して次の形式で出力したいデータがあります。

データ:

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)

希望の出力:

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

これを行うには、複数の仮想マシンをインポートする必要があります。

答え1

perlこれらの問題を解決するために設計および製造されています。 「病弱な折衷主義ゴミリスト」というニックネームがついた。

に関する記事を読んでください。実装する。ユーザーがする必要があるのは、データを読み取って(一度に1行ずつ)、解析して変数に入力し、定義したデータに基づいて現在のwriteデータを出力するコマンドを実行することです。format

データのヘッダー形式は次のとおりです。

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

各出力ラインに別のものがあります。

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

.

データを取得する方法はよくわかりませんが、2つの改行で区切られたファイルに保存するとします。各ホストは行ブロックです。

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)

入力区切り記号は次のように設定できます。

$/="\n\n";

読み取るたびに、フルテキストブロック、つまり仮想ホストのすべての行が取得されます。

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

これで面白いことが始まります。入力を解析することです。 whileループ内で次のことができます。

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;

解析は粗雑ですが、一般的に効果的です。

答え2

書式をどれだけ正確に指定するかによって異なりますが、通常はタブで区切るだけで十分ですが、私は次のようにアクセスします。

#!/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;   
}

これは、固定幅自体ではなく、タブストップに合わせて配置されます。ユースケースによっては、この方法がより適している可能性があります。それ以外の場合 -format上記のように使用するか、sprintf固定フィールド幅を使用できます。

#!/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;   
}

関連情報