Как я передаю хеш функции в Perl?

Сначала сгенерируйте массив аргументов, которые вы хотите передать, затем преобразуйте в форму, совместимую с оболочкой, используя @sh. Затем вы можете перейти к xargs для вызова команды.

$ jq -r '.[] | ["post", "create", (to_entries[] | "--\(.key)=\(.value|tojson)")] | @sh' input.json | xargs wp
38
задан Peter Mortensen 29 August 2016 в 13:02
поделиться

8 ответов

Передать ссылку вместо самого хеша. Как в

PrintAA("abc", \%fooHash);

sub PrintAA
{
  my $test = shift;
  my $aaRef = shift;

  print $test, "\n";
  foreach (keys %{$aaRef})
  {
    print $_, " : ", $aaRef->{$_}, "\n";
  }
}

См. Также perlfaq7: Как я могу передать / вернуть {Function, FileHandle, Array, Hash, Method, Regex}?

67
ответ дан 27 November 2019 в 03:10
поделиться

Используйте следующую подпрограмму для получения хеша или хешрефа - что бы ни пропустили :)

sub get_args { ref( $_[0] ) ? shift() : ( @_ % 2 ) ? {} : {@_}; }
sub PrintAA
{
  my $test = shift;
  my $aa = get_args(@_);;
  #then
  $aa->{somearg} #do something
  $aa->{anotherearg} #do something

}

Вызовите свою функцию так:

printAA($firstarg,somearg=>1, anotherarg=>2)

Или вот так (неважно):

printAA($firstarg,{somearg=>1, anotherarg=>2})

Или даже как это (неважно):

my(%hash) = ( 'aaa' => 1, 'bbb' => 'balls', 'ccc' => \PrintAA );

PrintAA("test", %hash);

ура!

0
ответ дан 27 November 2019 в 03:10
поделиться

Arguments to functions get flattened into a single array (@_). So it's usually easiest to pass hashes to function by reference.

To create a HASH:

my %myhash = ( key1 => "val1", key2 => "val2" );

To create a reference to that HASH:

my $href = \%myhash

To access that hash by reference;

%$href

So in your sub:

my $myhref = shift;

keys %$myhref;
2
ответ дан 27 November 2019 в 03:10
поделиться

All the above methods work, but this was always the way I preferred to do things like this:

sub PrintAA ($\%)
{
    my $test       = shift;
    my %aa         = ${shift()};
    print "$test\n";
    foreach (keys %aa)
    {
        print "$_ : $aa{$_}\n";
        $aa{$_} = "$aa{$_}+";
    }
}

Note: I also changed your code a bit. Perl's double-quoted strings will interpret "$test" to be the value of $test rather than the actual string '$test', so you don't need that many .s.

Also, I was wrong about how the prototypes work. To pass a hash, use this:

PrintAA("test", %hash);

To print a hash reference, use this:

PrintAA("test", %$ref_to_hash);

Of course, now you can't modify the hash referenced by $ref_to_hash because you're sending a copy, but you can modify a raw %hash because you're passing it as a reference.

3
ответ дан 27 November 2019 в 03:10
поделиться

В качестве альтернативы:

sub PrintAA
{
    my $test       = shift;
    my %aa         = @_;
        print $test . "\n";
        foreach (keys %aa)
        {
                print $_ . " : " . $aa{$_} . "\n";
                $aa{$_} = $aa{$_} . "+";
        }
}

Принципиально вам не хватает того, что ассоциативный массив не является единственным аргументом (хотя ссылка на ассоциативный массив есть, как в ответе Пола Томблина).

12
ответ дан 27 November 2019 в 03:10
поделиться

Этот код работает:

#!/bin/perl -w

use strict;

sub PrintAA
{
    my($test, %aa) = @_;
    print $test . "\n";
    foreach (keys %aa)
    {
        print $_ . " : " . $aa{$_} . "\n";
    }
}

my(%hash) = ( 'aaa' => 1, 'bbb' => 'balls', 'ccc' => \&PrintAA );

PrintAA("test", %hash);

Ключевым моментом является использование контекста массива в «(») выражении my () в функции.


Что на самом деле делает бизнес с контекстом массива ?

Кратко, это заставляет его работать правильно.

Это означает, что первое значение в массиве аргументов @_ назначено $ test , а остальные элементы присваиваются хэшу % aa . Учитывая то, как я это назвал, в @_ есть нечетное количество элементов, поэтому, как только первый элемент назначен на $ test , доступно четное количество элементов присваивать % aa , причем первый элемент каждой пары является ключом («aaa», «bbb», «ccc» в моем примере), а второй - соответствующим значением.

Можно было бы заменить % aa на @aa , в этом случае в массиве будет 6 элементов. Также было бы возможно заменить % aa на $ aa , и в этом случае переменная $ aa будет содержать значение 'aaa', а остальные значения в @_ будут игнорироваться присваиванием.

Если вы опустите круглые скобки вокруг списка переменных, Perl откажется компилировать код. Один из альтернативных ответов показал запись:

my $test = shift;
my(%aa) = @_;

Это в значительной степени эквивалентно тому, что я написал; разница состоит в том, что после двух моих операторов @_ содержит только 6 элементов в этом варианте, тогда как в одной моей версии он все еще содержит 7 элементов .

В SO определенно есть другие вопросы о контексте массива.


На самом деле, я не спрашивал о my ($ test,% aa) = @_; Я спрашивал о my (% hash) = ('aaa' => 1, 'bbb' => 'balls', 'ccc' => \ & PrintAA); против моего% hash = {'aaa' => 1, ...};

Разница в том, что нотация {...} генерирует хэш-ссылку, а нотация (...) генерирует список, который сопоставляется с хэшем (в отличие от хэша ref). Точно так же [...] генерирует массив ref, а не массив.

Действительно, измените «основной» код так, чтобы он читал: my (% hash) = {...}; и вы получаете ошибку во время выполнения (но не во время компиляции) - обрабатывайте номера строк с осторожностью, так как я добавил альтернативные кодировки в свой файл:

Reference found where even-sized list expected at xx.pl line 18.
...
Use of uninitialized value in concatenation (.) or string at xx.pl line 13.
16
ответ дан 27 November 2019 в 03:10
поделиться

Это похоже на вас должен передать ссылку на хеш.

sub PrintAA
{
   my $test = shift;
   my $aa = shift;
   if (ref($aa) != "HASH") { die "bad arg!" }
   ....
}

PrintAA($foo, \%bar);

Причина, по которой вы не можете сделать

my %aa = shift;

, заключается в том, что Perl объединяет все аргументы подпрограммы в один список, @_. Каждый элемент копируется, поэтому передача по ссылке также позволяет избежать этих копий.

4
ответ дан 27 November 2019 в 03:10
поделиться

Как обычно, есть несколько способов. Вот что Perl Best Practices , наиболее уважаемый из указателей стилей, говорит о передаче параметров в функции:

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

Но так как у вас есть только два, вы можете уйти;) передав их напрямую следующим образом:

my $scalar = 5;
my %hash = (a => 1, b => 2, c => 3);

func($scalar, %hash)

И функция определяется следующим образом:

sub func {
    my $scalar_var = shift;
    my %hash_var = @_;

    ... Do something ...
}

Было бы более полезно, если бы вы могли показать некоторый код.

4
ответ дан 27 November 2019 в 03:10
поделиться
Другие вопросы по тегам:

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