Perl脚本|使用HASH [英] Perl Scripting | using HASHes

查看:149
本文介绍了Perl脚本|使用HASH的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个如下所示的输入文件:

  = IP1 
abc [0]
abc [1]
abc [2]
= IP2
def [4]
def [8]
def [9]

$ b

我需要以下面的格式获得输出 - = IP1
abc [0-2]
= IP2
def [4,8-9]

我一直在尝试使用散列来实现上述目的,我读取文件的每一行,然后分割(用'[')每行,我保留第一部分作为关键字并再次读取该文件以将值保存在散列键的数组中。但我陷入了一个循环。任何人都可以提供如何实现上述的帮助?

解决方案

好的,这是我的解决方案。如果没有任何关于传入数据的更好的信息,它可能比所需的更复杂。

它保留数据 - = IP 头文件和 xyz [9] 值的顺序与第一次遇到的顺序相同。我将数字范围缩小的代码分隔为子程序范围



这只是阅读将数据从文件中读入数据结构%data @order 并再次打印出来。散列中的 @order 数组和 _order 子键用于保存遇到的值序列添加到每当一个新的密钥插入到相应的散列中

  use strict; 
使用警告;

my($ key,%data,@order); $(b
$ b while(<>){

chomp;

if(/ ^ = /){
$ key = $ _;
推送@order,$ key,除非$ data {$ key};
$ data {$ key} = {_order => []};
}
elsif(my($ key2,$ n)= /([^ \ [\] \s] +)\ [(\ d +)\] /){
my $ data = $ data {$ key};
push @ {$ data-> {_ order}},$ key2除非$ data-> {$ key2};
push @ {$ data-> {$ key2}},$ n;



为我的$ key(@order){

print $ key,\\\
;

my $ data = $ data {$ key};
$ b $ for my $ key2(@ {$ data-> {_ order}}){
printf%s [%s] \\\
,$ key2,ranges(sort { $ a< => $ b} @ {$ data-> {$ key2}});
}

}

子范围{

我的@ranges;
my($ start,$ end);

为我的$ n(@_){
if(未定义$ start){
$ start = $ end = $ n;
}
elsif($ n == $ end + 1){
$ end = $ n;
}
else {
push @ranges,$ start == $ end? $ start:$ start- $ end;
$ start = $ end = $ n;
}
}

push @ranges,$ start == $ end? $ start:$ start- $ end(如果已定义)$ start;
加入',',@ranges;



输出



 = IP1 
abc [0-2]
= IP2
def [4,8-9]


I have an input file which looks like below

 =IP1
abc[0]
abc[1]
abc[2]
=IP2
def[4]
def[8]
def[9]

I need to get the output in the below format -

=IP1
abc[0-2]
=IP2
def[4,8-9]

I have been trying to achieve the above using hashes where I read each line of the file and then split(with'[') each line, I keep the first part as key and read the file again to keep the values in an array for the hash keys. But I am getting stuck in a loop. Can anyone provide help on how to achieve the above ?

解决方案

Okay, here's my take on a solution. Without any better information on the incoming data it may be more complicated than necessary

It keeps the data -- both the =IP headers and the xyz[9] values in the same order that they are first encountered. I've separated out the generation of the number range contraction to subroutine ranges

It's simply a matter of reading the data in from the file -- which it expects as a parameter on the command line -- into data structures %data and @order and printing them out again. The @order array and the _order subkey of the hash are there to preserve the sequence that the values are encountered and are added to whenever a new key is inserted into the corresponding hash

use strict;
use warnings;

my ($key, %data, @order);

while ( <> ) {

  chomp;

  if ( /^=/ ) {
    $key = $_;
    push @order, $key unless $data{$key};
    $data{$key} = { _order => [] };
  }
  elsif ( my ($key2, $n) = /([^\[\]\s]+)\[(\d+)\]/ ) {
    my $data = $data{$key};
    push @{ $data->{_order} }, $key2 unless $data->{$key2};
    push @{ $data->{$key2} }, $n; 
  }
}

for my $key ( @order ) {

    print $key, "\n";

    my $data = $data{$key};

    for my $key2 ( @{ $data->{_order} } ) {
        printf "%s[%s]\n", $key2, ranges( sort { $a <=> $b } @{ $data->{$key2} } );
    }

}

sub ranges {

    my @ranges;
    my ($start, $end);

    for my $n ( @_ ) {
        if ( not defined $start ) {
            $start = $end = $n;
        }
        elsif ( $n == $end + 1 ) {
            $end = $n;
        }
        else {
            push @ranges, $start == $end ? $start : "$start-$end";
            $start = $end = $n;
        }
    }

    push @ranges, $start == $end ? $start : "$start-$end" if defined $start;
    join ',', @ranges;
}

output

=IP1
abc[0-2]
=IP2
def[4,8-9]

这篇关于Perl脚本|使用HASH的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆