Как я использую Perl для парсинга вывода команды sqlplus?

У меня есть файл 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 использования?

Править:

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

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
1
задан Vijay 3 May 2010 в 10:51
поделиться

3 ответа

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

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

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

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

my %hash; # the base object for the data

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

Следующим элементом является цикл foreach (который может быть сокращен как «для»). Цикл обработает список строк в @tmp_cycledef , назначая каждую по очереди $ row . ( мой $ row ).

  1. Мы сначала обрабатываем строку, удаляя символ конца строки для этой платформы.
  2. Мы разделили строку на '|' символ, создавая список строк, разделенных вертикальной чертой.
  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; 
}

Как только у нас есть данные в структуре, нам нужно повторить оба уровня хэш-ключей . Вы хотели разделить числа «верхнего уровня» строками, но вы хотели, чтобы вторые числа были объединены в одной строке.Итак, мы печатаем строку для каждого из первых чисел и соединяем список строк, хранящихся для каждого числа в одной строке, разделенных запятыми. Мы также сортируем список: {$ 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
ответ дан 3 September 2019 в 00:55
поделиться

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

#!/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
0
ответ дан 3 September 2019 в 00:55
поделиться

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

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
1
ответ дан 3 September 2019 в 00:55
поделиться
Другие вопросы по тегам:

Похожие вопросы: