I'm just starting out with perl. I want to set a boolean variable flag based on if the hash map has content or not. This tells me I can use a ! operator to check if hash empty. how to check if a hash is empty in perl
So I have this so far:
if (!%someHash){
$flag = false;
} else {
$flag = true;
}
Is this a best way of writing it or there is a simpler way?
Since perl doesn't have boolean types I've always just done:
my $flag = keys %someHash
Related
I need to compare two Perl object values, one is from a variable and another one is from an array value
ImmediateParent and data contain path directive values(C:\Users\Public\Documents)
while (length(basename(dirname(($immediateParent)))) > 1)
{
$immediateParent = (dirname(($immediateParent)));
my ($dictionaryitem) = $';
my $boolean =0;
foreach $dictionaryitem (#data)
{
if ($immediateParent eq $dictionaryitem->[0])
{
$boolean = 1;
last;
}
}
if ($boolean)
{
last;
}
}
I attempted to compare the values of two paths directories, but the condition always returned true, so it was ineffective. Would you kindly advise me on how to compare two path values?
If Data::Dumper shows
$immediateParent = 'C:\\Users\\Public';
$dictionaryitem = 'C:\\Users\\Public';
then you should compare them directly without array dereference, i.e. remove the ->[0]:
if ($immediateParent eq $dictionaryitem)
The fact that Perl let you dereference a string is weird. Are you not using strict?
In visudo Ubuntu I whitelist this program (I doing this way for security purpose, parameterized all commands)
myuser ALL=(root) NOPASSWD:/App/Filter_Parameters_Wrap.pm *
In program.pl
my $capture = qx("/usr/bin/sudo /App/Filter_Parameters_Wrap.pm kernel_version");
In the module Filter_Parameters_Wrap:
my $fuction = $ARGV[0];
print filters_dispatch($fuction) if defined $fuction;
sub filters_dispatch {
my $filter = shift;
my $dispatch = {
kernel_version => \&filter_kernel_version,
};
return $dispatch->{$filter}->();
}
sub filter_kernel_version {
my $command = '/bin/uname -a';
my $sudo = App::Sudo::Main_Sudo->root($command);
utf8::decode($sudo);
return $sudo;
}
This approach is working , but I have to do print in print filters_dispatch (print directly a variable string), so I can get the output of return of function filter_kernel_version in the variable $capture
In some cases inside the function filter_kernel_version I want to create a hash and return as anonymous hash without print directly, but this way is not working
can you recommend a better approach?
No matter what option you use to communicate between processes, you'll be limited to sending a sequence of bytes. This means that you will need to serialize your hash somehow. Encoding it using JSON (e.g. using Cpanel::JSON::XS) might be a simple way of doing that.
recently started doing perl. I'm reading old code and trying to rewrite some stuff. I've got a question here about hash references.
#declar anon hash ref that will be returned
my $store_hash = {};
foreach my $item (#list)
{
#this will iterate based on list
my $ret_hash = ops_getval($item, $user)
#do some magic here to map $ret_hash into $store_hash
}
ops_getval is a function that returns a type of ref hash. I want to insert those values into $store_hash. How should I approach this? Can I directly do
$store_hash = ops_getval($var1,$var2)
Much appreciated!
I think the standard way to do this is:
#$store_hash{ keys %$ret_hash } = values %$ret_hash;
This merges all of the hashes returned by all of the calls to ops_getval into $store_hash.
An alternate approach that might be clearer to the eye, possibly at the cost of a lot of redundant data copying:
%$store_hash = (%$store_hash, %$ret_hash);
You would do something like:
$store_hash->{$item} = $ret_hash
In general:
$hashref->{$key} = $value
See here for more: http://perldoc.perl.org/perlref.html#Using-References
To be clear, you can use a loop and get this done.
foreach ( keys%{ $ret_hash } ){
$store_hash->{ $_ } = $ret_hash->{ $_ } ;
}
I find myself often writing code like this:
if ($optionalParamsRef->{verbosity}) {
$settingsHash{verbosity} = $optionalParamsRef->{verbosity};
}
However, it seems very verbose to repeat $optionalParamsRef->{verbosity} twice. Is there a shorter way?
Edit: Yes, I realize this is checking for true/false and not 'exists'. What I'm looking for is a concise functional equivalent to this.
Note you are checking $optionalParamsRef->{verbosity} for true, not exist.
Possible way to do this:
foreach my $k (qw/verbosity param1 param2 param3/) { #Enumerate keys here
$settingsHash{$k} = $optionalParamsRef->{$k} if exists($optionalParamsRef->{$k});
}
As others mentioned, your code checks for false-ness. If you considered false values as non-existant, you could have used the logical or. Probably this is not what you want.
$settingsHash{verbosity} = $optionalParamsRef->{verbosity} || $default;
But maybe defined-ness is enough. It's still no check for existence, but if your hash doesn't contain undef values, this could be enough:
$settingsHash{verbosity} = $optionalParamsRef->{verbosity} // $default;
using the "new" defined-or operator // instead of the logical or ||. I know these examples are not equivalent to the code you posted because they alwas assign something, but in my experience, this is often useful, so maybe it could help.
my $v = $optionalParamsRef->{verbosity};
$settingsHash{verbosity} = $v if $v;
for ($optionalParamsRef->{verbosity}) {
$settingsHash{verbosity} = $_ if $_;
}
A concise functional equivalent:
sub {$_[0]=$_[1] if $_[1]}->($settingsHash{verbosity}, $optionalParamsRef->{verbosity});
However, IMO, the main problem with your code is that you are only conditionally setting $settingsHash{verbosity}, keeping you from doing something simpler like:
$settingsHash{verbosity} = $optionalParamsRef->{verbosity} || somedefault
or even:
%settingsHash = ( %defaultSettings, %$optionalParamsRef );
Is it safe/good practice in Perl to use an empty string as false in boolean comparisons?
ex:
my $s = '';
if($s) {
print 'true';
} else {
print 'false';
}
or would the length function be a better way to go:
my $s = '';
if(length($s) > 0) {
print 'true';
} else {
print 'false';
}
When testing for true/false in an expression, you should think carefully about what you actually want to test.
If you have a string and you need to check if it has any value at all, then test for that:
if (defined $string) { ... }
If you are passing back a "boolean" value from a function, or testing the result of some internal operation, then perform a boolean check:
if ($value) { ... }
In Perl, "truth" depends on the manner in which it is evaluated. If you simply say if ($value), then the only string values that evaluate to false are the empty string '', and a literal zero '0'. (Also, any undefined value is false, so if $value has never been assigned, that would be false too.)
There are other values which may evaluate to false in a numerical context, for example 0E0, 0.0000, and the string '0 but true'. So the question "what is truth" really depends on the context, which you the programmer need to be aware of.
Internally, Perl uses '' for false and 1 for truth (for example as the result of any boolean expression such as !$value). A common technique for "canonicalizing" any value into one of these two values is !!$value -- it inverts a value twice, giving you either '' or 1.
A string can have length but still be false -- specifically, the string '0' (details: Perl Truth and Falsehood). At least in the general case, length does not provide a robust test for truth.
my $s = '0';
print "'0' is false.\n" unless $s;
print "But it has length.\n" if length $s;
Typically, you should use the test the characteristic that expresses what you really care about. For example, if you ask a user to enter his favorite age, '0' is a false but valid response: "My first year of life was great, and then everything went to hell."