Can I create an array of functions in Powershell? - arrays

I would like to have an array that contains a set of functions that I can iterate through and call. The issue is that the functions all run via the line that adds them to the array (ie. $scripts).
Example:
function Hello
{
$BadFunction = "Hello"
Write-Host "Hello!"
}
function HowAreYou
{
$BadFunction = "HowAreYou"
Write-Host "How are you?"
#$false = $true
}
function Goodbye
{
$BadFunction = "Goodbye"
Write-Host "Goodbye!"
}
$scripts = #((Hello), (HowAreYou), (Goodbye))
foreach ($script in $scripts)
{
$script
}

Functions can only be called by using their name, not referenced, but you can get the scriptblock via the Function: drive:
$scripts = $Function:Hello, $Function:HowAreYou, $Function:GoodBye
# call them with the & operator
$scripts | ForEach-Object { & $_ }
# You can also call them by calling Invoke on the scriptblock
$scripts | ForEach-Object Invoke

Joey's answer contains good information, but if all you need is to reference your functions by name, define your array as containing the function names as strings, and invoke the functions by those strings with &, the call operator:
function Hello { "Hello!" }
function HowAreYou { "How are you?" }
function Goodbye { "Goodbye!" }
# The array of function names *as strings*.
# Note that you don't need #(...) to create an array.
$funcs = 'Hello', 'HowAreYou', 'Goodbye'
foreach ($func in $funcs)
{
# Use & to call the function by the name stored in a variable.
& $func
}
The issue is that the functions all run via the line that adds them to the array (ie. $scripts).
That's because your array elements are expressions (due to the enclosing (...)) that call the functions (e.g., (Hello) calls Hello and makes its output the array element), given that they're being referenced without single- or double-quoting.
Unlike in, say, bash, you cannot define string array elements as barewords (tokens without enclosing single- or double-quoting); for instance, the following is a syntax error in PowerShell:
# !! Does NOT work - strings must be quoted.
$funcs = Hello, HowAreYou, GoodBye # ditto with #(...)

Related

Changing an array in Perl

I am trying to use Perl to parse output from a (C-based) program.
Every output line is a (1D) Perl array, which I sometimes want to store (based on certain conditions).
I now wish to (deep) copy an array when its first element has a certain keyword,
and print that same copied array if another keyword matches in a later line-array.
So far, I have attempted the following:
#!/usr/bin/env perl
use strict; # recommended
use Storable qw(dclone);
...
while(1) # loop over the lines
{
# subsequent calls to tbse_line contain
# (references to) arrays of data
my $la = $population->tbse_line();
my #copy;
my $header = shift #$la;
# break out of the loop:
last if ($header eq 'fin');
if($header eq 'keyword')
{
#copy = #{ dclone \#$la };
}
if($header eq 'other_keyword')
{
print "second condition met, print first line:\n"
print "#copy\n";
}
}
However, this prints an empty line to the screen, instead of the contents of the copied array. I don't have a lot of Perl experience, and I can't figure out what I am doing wrong.
Any idea on how to go about this?
my #copy allocates a new Perl array named #copy in the current scope. It looks like you want to set #copy during one iteration of your while loop and print it in a different iteration. In order for your array not to be erased each time a new while loop iteration starts, you should move the my #copy declaration outside of the loop.
my #copy;
while (1) { ... }

get param function array in perl

I want to get the array that I send in my function but it seem's to be empty.
I call send_file(); with an array in the param
send_file($addr, #curfile);
And this is the way I get back the param
sub send_file($$)
{
my $addr = $_[0];
my #elem = #_;
...
}
Why my #elem is empty ? How could I get back the array without losing everything ?
Don't use prototypes. Their purpose is to change parsing of the source which you don't need.
sub send_file
{
my $addr = shift;
my #elem = #_;
...
}
send_file($addr, #curfile);
You should pass your array by reference instead:
#!/usr/bin/perl
use strict;
use warnings;
my $test_scalar = 10;
my #test_array = qw(this is a test);
sub test($\#)
{
my ($scalar, $array) = #_;
print "SCALAR = $scalar\n";
print "ARRAY = #$array\n";
}
test($test_scalar, #test_array);
system 'pause';
Output:
SCALAR = 10
ARRAY = this is a test
Press any key to continue . . .
EDIT:
If you would like to do the same thing without passing by reference change your $$ to $# and use shift so the first argument doesn't end up included in your array. Passing arrays by reference is better coding practice though . . . This is just to show you how it can be done without passing by reference:
#!/usr/bin/perl
use strict;
use warnings;
my $test_scalar = 10;
my #test_array = qw(this is a test);
sub test($#)
{
my ($scalar, #array) = #_;
print "SCALAR = $scalar\n";
print "ARRAY = #array\n";
}
test($test_scalar, #test_array);
system 'pause';
This will get you the same output.
You can also get rid of the $# altogether if you would like it really isn't necessary.
Why my #elem is empty ?
Your #elem is not empty, it has exactly two elements. First is value of $addr and second is size/number of elements in #curfile array. This is due $$ prototype definition which requires two scalars, so scalar #curfile is passed as second parameter.
How could I get back the array without loosing everything ?
Since you're not using prototype advantages, just omit prototype part,
sub send_file {
my ($addr, #elem) = #_;
...
}

Match caller function using regular expressions

I am trying to use grep to find all the callers of a particular C function.
E.g.:
void foo()
{
...
ret = my_bar()
}
For all occurrances of my_bar() I want to print the corresponding function name from where my_bar() is called.
I have tried (based on Regex (grep) for multi-line search needed)
grep -Pzo "(?s)^{\N*?.*?my_bar" *.c
using Perl regex, but this doesn't quite work as expected. It starts the match at the function before foo() till my_bar()
Is this possible with grep/perl and regex, or will I have to use tools like cscope?
A Perl one-liner that remembers the last function, and prints its name when my_bar() is found. This is quite simplistic, it'll print a function multiple times if it calls my_bar() multiple times, but you get the basic idea.
perl -ne '$fun = $_ if /^\w+ \w+\(.+\)$/; if (/my_bar\(\)/) { print "$fun" }' *.c
The variant below should cover functions with multi-line argument lists and trailing comments as well:
perl -ne '$fun = $_ if /^\w+ \w+\(.+$/; if (/my_bar\(\)/) { print "$fun" }' *.c

How to pass index of array in cmd line argument which is function pointer and call to specific function in perl?

Suppose I have 2 functions in Perl. I would create a array of references of that two functions. & in command line argument I'll pass only that index of array which call specific function and if I don't give any argument then it'll call all functions which referenced were in array(Default case).
So, can any help me to do this?
## Array content function pointers
my #list= {$Ref0,$Ref1 }
my $fun0Name = “fun0”;
my $Ref0 =&{$fun0Name}();
my $fun1Name = “fun1”;
my $Ref1 =&{$fun1Name}();
#### Two functions
sub fun0() {
print "hi \n";
}
sub fun1() {
print "hello \n";
}
##### Now in cmd argument if i passed Test.pl -t 0(index of array ,means call to 1st function)
##### if i give test.pl -t (No option ) ....then i call both function.
Creating a function pointer (called a code reference in Perl) is easy enough:
sub foo {
say "foo!";
}
sub bar {
say "bar!";
}
my $foo_ref = \&foo;
my $bar_ref = \&bar;
Putting things in an array is pretty easy:
my #array = ( $foo_ref, $bar_ref );
Reading arguments from the command line is pretty easy:
my $arg = shift #ARGV;
Looking things up in an array is also pretty easy:
my $item = $array[$arg];
Which part are you having trouble with?

What is the value if you shift beyond the last element of an array?

In this piece of code, shift is used twice, even though the method only takes one parameter:
sub regexVerify ($)
{
my $re = shift;
return sub
{
local $_ = shift;
m/$re/ ? $_ : undef;
};
}
What does this make the value of local $_, once shift is used again? I was (perhaps naively) assuming that shifting into nothingness would result in undef. But if that were true, this line has no meaning, right?:
m/$re/ ? $_ : undef;
The above sub is called like:
regexVerify (qr/^([a-z].*)?$/i);
The second shift is inside the inner sub declaration. That scope will have an entirely new #_ to work with, which won't have anything to do with the #_ passed to the outer subroutine.
regexVerify is a subroutine that returns another subroutine. Presumably you would later invoke that subroutine with an argument:
my $func = regexVerify(qr/^([a-z].*)?$/i);
# $func is now a "code reference" or "anonymous subroutine"
...
if ($func->($foo)) { # invoke the subroutine stored in $func with arg ($foo)
print "$foo is verified.\n";
} else {
print "$foo is not verified!\n";
}
local $_ = shift; doesn't get executed until you make call to anonymous function. ie
my $anon_func = regexVerify (qr/^([a-z].*)?$/i);
# NOW sending arguments in #_ for local $_ = shift;
print $anon_func->("some string");

Resources