데이터 구성

데이터 구성

쉘/펄 스크립트를 사용하여 다음 형식으로 출력하려는 ​​일부 데이터가 있습니다.

데이터:

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이러한 문제를 해결하기 위해 설계 및 제조되었습니다. "병약한 절충주의 쓰레기 목록"이라는 별명이 붙었습니다.

에 관한 문서를 읽어보세요.구현하다. 사용자가 해야 할 일은 데이터를 읽고(예: 한 번에 한 줄씩) 구문 분석하고 변수에 채운 다음 정의한 데이터를 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)

.

데이터를 어떻게 얻는지는 잘 모르겠지만 두 개의 줄 바꿈으로 구분된 파일에 저장한다고 가정해 보겠습니다. 각 호스트는 행 블록입니다.

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;   
}

관련 정보