2012-09-26 50 views
1

我有以下格式的数据输出。 我从控制台上的命令获取此输出。Perl - 格式化输出数据

Number: 9 
state: Online 
Data:    W1F-9YN 
Device: 41 
Number: 10 
state: Online 
Inquiry Data:    W1-9YN     
Device: 41 
Number: 11 
state: Online 
Inquiry Data:    W1-9YN     
Device: N/A 
Number: 42 
state: Online 
Data:  WD-W WDZ-04J     

但是,现在我想将其更改为输出表格格式。 就像如下图所示

Device number state data 
41  10  online WY1-996 
42  12  offline WY2-996 
.   .  .  . 
.   .  .  . 
.   .  .  . 

我试着用如下的代码做的,但我不能够在正确的格式和一段时间在一个单一的列中的所有数据显示,高达安排。任何人都可以帮我吗?

open WDLIST, "Command"; 

while (<WDLIST>) { 

    if (m/Device\s*:\s*(\d+)/) { 

     $enDevice = $1; 
     print "$enDevice"; 
    } 

    if (m/Number\s*:\s*(\d+)/) { 

     $umber = $1; 
     print "$Number"; 
     chomp; 
    } 

    if (m/state\s*:\s*(w+)/) { 

     $State = $1; 
     print"$State"; 
    } 

    if (m/Data\s*:\s*(w+)(d+)(\-)(\s)/) { 

     $Data = $1; 
     print"$Data"; 
    } 
} 

谢谢!

+0

这很像http://stackoverflow.com/questions/12606045/converting-form-layout-to-table-csv-layout- in-perl – RobEarl

+0

这个问题似乎只对每个输入文件有一行数据,对于简单的数据CSV文件格式化起来要容易得多。 (直到你意识到你的数据可以包含逗号和引号) – pmakholm

+0

一些提示:1.你没有正确匹配最后一行。确保你的正则表达式匹配你想要捕捉的东西。 2. $ umber - 是一个错字吗? 3.您不打印制表符,并且不打印换行符。 – Bitwise

回答

1

您可以使用printf格式化输出。最简单的解决办法是用

printf "%-10s", $variable; 

这全部更换打印语句将打印变量留在10个字符宽列合理的。此外,您需要在每个数据块的开始或结束处打印换行符。

更完整的解决方案,我会收集所有数据的哈希值的行,只要你检测数据块的末尾打印:

printf "%-10s %-10s %-10s %-10s\n", $info{device}, $info{number}, $info{state}, $info{data}; 

(或使用散列切片更简洁代码)

基于每个Device字段表示新设备的开始的假设。我会改变你的代码来完成工作:

open WDLIST, "Command"; 

my %device; 

printf "%-10s %-10s %-10s %-10s\n", qw(Device number state data); 
while (<WDLIST>) { 
    if (m/Device\s*:\s*(\d+)/) { 

     # Print previous device, if any. 
     printf "%-10s %-10s %-10s %-10s\n", @data{ qw(id number state data) } 
      if exists $device{id}; 

     # Reset the current device and set the id 
     %device = (id => $1); 
    } 

    if (m/Number\s*:\s*(\d+)/) { 
     $device{number} = $1; 
    } 

    if (m/state\s*:\s*(w+)/) { 
     $device{state} = $1; 
    } 

    if (m/Data\s*:\s*(w+d+-\d+)/) { 
     $device{data} = $1; 
    } 
} 
# Print the last device (if any) 
printf "%-10s %-10s %-10s %-10s\n", @data{ qw(id number state data) } 
    if exists $device{id}; 

(我有点不确定什么数据field最后的正则表达式真的应该是你的榜样是不相符的,至少你会需要解释。示例输入的数据字段与示例输出之间的关系)

+0

如果我在block的结尾处打印换行符,如果block或while block?如果我在每个if循环的末尾添加一个新行,它只是给出新行。你如何收集一行数据。你可能会看到前三名应该排在第一排,接下来的三排应该排在前面?对于为什么它是单列打印,我也很困惑。如果我给tab也不起作用。 – JumpOffBox

+0

在这两种情况下都没有提到数据块。您需要一种方法来确定哪些字段属于一起。根据你的例子,可能每个设备都以“Device:”字段开始。 – pmakholm

+0

谢谢麦。 但是你在哪里打印这些数据。我尝试了你发布的想法,但它不打印任何东西。 – JumpOffBox