Сначала сгенерируйте массив аргументов, которые вы хотите передать, затем преобразуйте в форму, совместимую с оболочкой, используя @sh
. Затем вы можете перейти к xargs для вызова команды.
$ jq -r '.[] | ["post", "create", (to_entries[] | "--\(.key)=\(.value|tojson)")] | @sh' input.json | xargs wp
Передать ссылку вместо самого хеша. Как в
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}?
Используйте следующую подпрограмму для получения хеша или хешрефа - что бы ни пропустили :)
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);
ура!
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;
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.
В качестве альтернативы:
sub PrintAA
{
my $test = shift;
my %aa = @_;
print $test . "\n";
foreach (keys %aa)
{
print $_ . " : " . $aa{$_} . "\n";
$aa{$_} = $aa{$_} . "+";
}
}
Принципиально вам не хватает того, что ассоциативный массив не является единственным аргументом (хотя ссылка на ассоциативный массив есть, как в ответе Пола Томблина).
Этот код работает:
#!/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.
Это похоже на вас должен передать ссылку на хеш.
sub PrintAA
{
my $test = shift;
my $aa = shift;
if (ref($aa) != "HASH") { die "bad arg!" }
....
}
PrintAA($foo, \%bar);
Причина, по которой вы не можете сделать
my %aa = shift;
, заключается в том, что Perl объединяет все аргументы подпрограммы в один список, @_. Каждый элемент копируется, поэтому передача по ссылке также позволяет избежать этих копий.
Как обычно, есть несколько способов. Вот что 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 ...
}
Было бы более полезно, если бы вы могли показать некоторый код.