Как мне использовать Perl для разбора вывода команды sqlplus? - PullRequest
1 голос
/ 01 мая 2010

У меня есть файл SQL, который выдаст мне вывод, как показано ниже:

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

Я использую это в скрипте Perl, как показано ниже:

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

после этого оператора, так как @tmp_cycledef имеет все выходные данные SQL-запроса, Я хочу показать вывод как:

10 1,2,3
11 2,4

Как я могу сделать это, используя Perl?

EDIT:

Я использую следующий код:

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 ]

1 голос
/ 01 мая 2010

Ну, на самом деле, это то, как вы могли бы сделать это в perl :

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

Perl позволяет создавать переменные по мере их использования, $feldman = some_function() означает, что теперь у вас есть переменная $feldman в вашем локальном пространстве имен. Но самое плохое в этом то, что вы можете набрать $fldman и потратить много времени на выяснение того, почему то, что вы считали $feldman, не имеет значения. Включение strictures означает, что ваш код не сможет скомпилироваться, если он обнаружит необъявленную переменную. Вы объявляете переменную с помощью оператора my или our (или в более старом коде Perl оператор use vars.

Включение warnings просто предупреждает вас, когда вы не получаете ожидаемые значения. Часто предупреждения, как правило, слишком обидчивы, но они обычно - хорошая вещь для разработки кода с помощью.

my %hash; # the base object for the data

Здесь я объявил хеш-переменную, которую я творчески назвал %hash. Символ (произносится как "sijil") "%" говорит о том, что это карта пар имя-значение. Эта my инструкция объявила переменную и делает ее допустимой для компилятора. Компилятор предупредит меня о любом использовании %hsh.

Следующим элементом является цикл foreach (который может быть сокращен до «для»). Цикл обработает список строк в @tmp_cycledef, присваивая каждую по очереди $row. ( my $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.

Чтобы помочь вам, вам действительно нужно прочитать некоторые из них:

1 голос
/ 01 мая 2010

Используйте хэш массивов , чтобы собрать все значения для одного ключа вместе, а затем распечатать их:

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
0 голосов
/ 01 мая 2010

Если ваш вход отсортирован (как в приведенном примере), вам на самом деле не нужно беспокоиться о хэше массивов / хэшей. Код немного длиннее, но не требует понимания ссылок и должен работать быстрее для больших наборов данных:

#!/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
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...