代码之家  ›  专栏  ›  技术社区  ›  Vijay

如何使用Perl解析sqlplus命令的输出?

  •  1
  • Vijay  · 技术社区  · 16 年前

    我有一个SQL文件,它将提供如下输出:

    10|1
    10|2
    10|3
    11|2
    11|4
    .
    .
    .
    

    我在Perl脚本中使用它,如下所示:

    my @tmp_cycledef = `sqlplus -s $connstr \@DLCycleState.sql`;
    

    @tmp_cycledef

    10 1,2,3
    11 2,4
    

    如何使用Perl实现这一点?

    编辑:

    foreach  my $row (@tmp_cycledef)
    {
            chomp $row;
            my ($cycle_code,$cycle_month)= split /\s*\|\s*/, $row;
            print "$cycle_code, $cycle_month\n";
            $hash{$cycle_code}{$cycle_month}=1
    }
    
    foreach my $num ( sort keys %hash )
    {
            my $h = $hash{$num};
            print join(',',sort keys %$h),"\n";
    }
    

         2, 1
         2, 10
         2, 11
         2, 12
         3, 1
         3, 10
         3, 11
    

    但问题总是解决的

    1,10,11,12
    1,10,11,12
    1,10,11,12
    1,10,11,12
    1,10,11,12
    1,10,11,12
    1,10,11,12
    
    3 回复  |  直到 16 年前
        1
  •  1
  •   Axeman maxelost    16 年前

    好吧,这一个实际上是你可以做的 :

    # two must-have pragmas for perl development
    use strict;    
    use warnings;
    

    Perl允许在使用变量时创建变量, $feldman = some_function() $feldman 在本地命名空间中。但最糟糕的是你会打字 $fldman 花了很长时间才知道你为什么这么想 没有价值。打开 strictures 意味着如果代码遇到未声明的变量,它将无法编译。声明一个带有 my our 语句(或在旧的Perl代码中) use vars 声明。

    打开 warnings 当你没有得到你所期望的价值时,只会发出警告。警告往往过于敏感,但事实并非如此 通常地 发展 用编码。

    my %hash; # the base object for the data
    

    在这里,我声明了一个我创造性地调用的哈希变量 %hash . sigil(发音为“sijil”)“%”表示它是名称-值对的映射。这个 my 陈述 %hsh

    下一项是 foreach @tmp_cycledef 依次分配给 $row . ( 我的 $行 ).

    1. 我们 chomp
    2. 我们 split
    3. 然后我们把它存储在一个两层的散列中。因为我们至少要按第一个数字来分组。我们可以通过数组来实现这一点,并在哈希中的位置创建一个数组,如下所示: push @{$hash{$key}}, $val ,但我通常希望折叠重复项(并不是说您的示例中有任何重复项)

    在这里:

    foreach my $row ( @tmp_cycledef ) { 
        chomp $row; # removes the end-of-line character when present. 
        my ( $key, $val ) = split /\|/, $row; 
        # One of the best ways to merge lists is a presence-of idea
        # with the hash holding whether the value is present
        $hash{$key}{$val} = 1; 
    }
    

    keys . 您希望将“顶级”数字按行分隔,但希望第二个数字串联在同一行上。所以我们为每个第一个数字打印一行 join 为同一行中的每个数字存储的字符串列表,用逗号分隔。我们也 分类 列表: { $a <=> $b } 数字 比较它们。所以你得到一个数字顺序。

    # If they were alpha keys our sort routine, we would just likely say sort keys %hash
    foreach my $num ( sort { $a <=> $b } keys %hash ) { 
        my $h = $hash{$num};
        print "$num ", join( ',', sort { $a <=> $b } keys %$h ), "\n";
    }
    

    正如我在评论中所说, sort ,默认情况下,按字符顺序排序,这样您就可以说 sort keys %hash

    为了帮助您,您确实需要阅读以下内容:

        2
  •  1
  •   Klaus Byskov Pedersen    16 年前

    hash of arrays 要收集单个键的所有值,然后将它们打印出来:

    init hash
    for each line:
      parse into key|value
      append value to hash[key]
    
    for each key in hash:  # you can sort it, if needed 
      print out key, list of values
    
        3
  •  0
  •   Dave Sherohman    16 年前

    如果您的输入已排序(如所提供的示例中所示),则实际上不需要处理数组/散列的散列。代码稍微长一点,但不需要理解引用,对于大型数据集,应该运行得更快:

    #!/usr/bin/perl
    
    use strict;
    use warnings;
    
    my @tmp_cycledef = <DATA>;
    
    my $last_key;
    my @values;
    for (@tmp_cycledef) {
      chomp;
      my ($key, $val) = split '\|';
    
      # Seed $last_key with the first key value on the first pass
      $last_key = $key unless defined $last_key;
    
      # The key has changed, so it's time to print out the values associated
      # with the previous key, then reset everything for the new one
      if ($key != $last_key) { 
        print "$last_key " . join(',', @values) . "\n";
        $last_key = $key;
        @values = ();
      }
    
      # Add the current value to the list of values for this key
      push @values, $val;
    }
    
    # Don't forget to print out the final key when you're done!
    print "$last_key " . join(',', @values) . "\n";
    
    __DATA__
    10|1
    10|2
    10|3
    11|2
    11|4