redtux has asked for the wisdom of the Perl Monks concerning the following question:

Hi I have a sub routine which reads in the result of thousands of open3 calls (ffprobe for info) and parses the results. Everything works fine except for uninitialized warnings for about 400 out of around 33k entries Trying to get the the values that are missing is proving problematic
foreach my $file (keys %hash){ foreach my $opt (keys %{$hash{$file}}){ if (!(defined $opt,$hash{$file}->{$opt})){ say '9809 ', join '|',$file,$opt,$hash{$file}->{$opt}; } $hash{$file}->{$opt}=~s/[^[:ascii:]]//gxms; my $lined=join ("\t",$file,$opt,$hash{$file}->{$opt})."\n"; }
This gives initialized warnings on the last two lines if the value is blank. However I cant seem to get the problems lines to check. The defined check at the top prints everything that is either blank or 0. However 0 is a fully valid value, not undef. If I test for true (if ($hash{$file}->{$opt}){}), everything with a zero gets removed. Is there any way around this? (I'm probably missing something basic here) thanks Mike

Replies are listed 'Best First'.
Re: defined and value is 0
by Athanasius (Archbishop) on Jul 06, 2020 at 14:14 UTC

    Hello redtux,

    This line:

    if (!(defined $opt,$hash{$file}->{$opt})){

    is probably not doing what you expect. From Comma Operator:

    Binary "," is the comma operator. In scalar context it evaluates its left argument, throws that value away, then evaluates its right argument and returns that value. This is just like C's comma operator.

    As hippo has shown, you want a logical AND (i.e., &&) here rather than a comma.

    Hope that helps,

    Athanasius <°(((><contra mundum Iustus alius egestas vitae, eros Piratica,

      Many apologies, I noticed that just before you posted. Removed the key ($opts) and everything works right
Re: defined and value is 0
by hippo (Archbishop) on Jul 06, 2020 at 12:56 UTC

    It's not entirely clear to me quite what you want. However, here's an SSCCE showing one way to avoid processing the undef values.

    use strict; use warnings; use feature 'say'; use Test::More tests => 2; use Test::NoWarnings; my %foo = ( a => 1, b => 0, c => '', d => undef ); my $lined = ''; foreach my $opt (sort keys %foo) { unless (defined $opt && defined $foo{$opt}) { no warnings 'uninitialized'; say '9809 ', join '|', $opt, $foo{$opt}; next; } # Only run these if $foo{$opt} is defined; $foo{$opt} =~ s/[^[:ascii:]]//gxms; $lined .= join ("\t", $opt, $foo{$opt})."\n"; } is $lined, "a\t1\nb\t0\nc\t\n";

    Note that your indentation is rather misleading and you haven't closed the outer loop. I've removed that outer loop here for simplicity.

Re: defined and value is 0
by BillKSmith (Monsignor) on Jul 06, 2020 at 14:58 UTC
    Your code would produce the messages you posted if used with the following hash. The code below correctly skips the problem data.
    use strict; use warnings; use feature 'say'; my %hash = ( file0 => { opt0 => undef, opt1 => 1 }, file1 => { opt0 => 0, opt1 => 1 }, ); foreach my $file ( keys %hash ) { my %temp = %{ $hash{$file} }; OPTION: foreach my $opt ( keys %temp ) { if ( !exists $hash{$file} or !exists $hash{$file}{$opt} or !defined $hash{$file}{$opt} ) { warn "Option does not exist\n"; next OPTION; } $hash{$file}->{$opt} =~ s/[^[:ascii:]]//gxms; my $lined = join( "\t", $file, $opt, $hash{$file}->{$opt} ) . "\n"; } }
    Bill