Beefy Boxes and Bandwidth Generously Provided by pair Networks
Keep It Simple, Stupid
 
PerlMonks  

Wrong content of variable passed to sub

by olafmar (Novice)
on Aug 20, 2013 at 22:48 UTC ( #1050262=perlquestion: print w/ replies, xml ) Need Help??
olafmar has asked for the wisdom of the Perl Monks concerning the following question:

Actually I'm not sure I'm asking in the correct place, but I try my best. I have this snippet:
#!/bin/perl use strict; add_iLO3_data(); exit; sub add_iLO3_data() { $_ = "Memory | 0x0 | discrete | 0x4080| na + | na | na | na | na | na "; chomp; my @fields = split(/\|/); my $name = $fields[0]; $name =~ s/\s*//; $name =~ s/\s*$//; my $value = $fields[1]; $value =~ s/\s*//; $value =~ s/\s*$//; my $status = $fields[3]; $status =~ s/\s*//; $status =~ s/\s*$//; print "$name--$value--$status--\n"; # add to database my $id = get_sensor_id($name); my @variables = ("sensor_id", "OperationalStatus", "CurrentReading +"); my @readings = ($id, $value, $status); # here I add to DB } sub get_sensor_id($) { my $sensor = $_; print "sensor input: $sensor\n"; return 0; }
and I get as output:
Memory--0x0--0x4080-- sensor input: Memory | 0x0 | discrete | 0x4080| na + | na | na | na | na | na

The goal of the complete script is to parse an output and save some log data to a sqlite3 database, I cut out most of it.

I would expect to get in $sensor only "Memory", since I pass the variable $name by value (I tried by reference as well) and, as shown in the first sub, the variable $name seemed fine.

Where am I wrong?

Thank you very much!

Comment on Wrong content of variable passed to sub
Select or Download Code
Re: Wrong content of variable passed to sub
by state-o-dis-array (Hermit) on Aug 20, 2013 at 22:55 UTC
    Try this in your sub:
    sub get_sensor_id($) { my ($sensor) = @_; print "sensor input: $sensor\n"; return 0; }
    There are some other things I would do differently (like:
    $value =~ s/^\s+|\s+$//g;
    ), but this should address your primary concern.

      I thought that @_ meant the list passed to the sub, so I used $_ when I passed a single element. My bad, I should have read perlsub better (or simply reread it).

      I used your new regexp together with the suggestions below.

        I thought that @_ meant the list passed to the sub, so I used $_ when I passed a single element.

        @_ contains the list of arguments for a sub, but you want the first argument of that array, which is $_[0]. $_ is something completely different, as you already know.

        There are two common idioms for accessing arguments:

        sub foo { my $onlyarg=shift; # @_ is the default argument for shift # more code }

        and

        sub bar { my ($huey,$dewey,$louie)=@_; # more code }

        Of course, you can also write

        sub baz { my $onlyarg=$_[0]; # more code }

        or

        sub moo { my $huey=shift; my $dewey=shift; my $louie=shift; # more code }

        or even

        sub ohnononononopleaseno { my $huey=$_[0]; my $dewey=$_[1]; my $louie=$_[2]; # more code }

        But that is uncommon and has some strange accent. Stick with the first two variants. Having only one argument needs no exception, you can use the list assignment even for a single argument, no need for shift:

        sub foo2 { my ($onlyarg)=@_; # more code }

        Just remember the parentheses, or else $onlyarg will contain the number of arguments, in this case 1. Not what you want.

        Alexander

        --
        Today I will gladly share my knowledge and experience, for there are no sweeter words than "I told you so". ;-)
Re: Wrong content of variable passed to sub
by AnomalousMonk (Monsignor) on Aug 20, 2013 at 23:33 UTC

    In addition to the critical problem diagnosed by state-o-dis-array, here are my candidates for things I would do differently:

    sub get_sensor_id($) { ... }

    Don't use prototypes (the  ($) thingy in the above function definition). It didn't help you in the present case, and they probably don't do what you think they do, so why bother? Please see Prototypes in perlsub and Far More than Everything You've Ever Wanted to Know about Prototypes in Perl -- by Tom Christiansen.

    sub add_iLO3_data() { $_ = "Memory (a whole buncha stuff) "; chomp; ... }

    chomp chomps a newline (in the default case) from the end of the  $_ default scalar if no other variable is specified to chomp, as in the code above. But you just finished assigning a string to $_. If you don't want a newline at the end of it, just don't put one there in the first place — as indeed you did not! No point in chomp-ing.

    (Same code extract.) Don't use global variables, e.g.  $_ in the code above, unless you really know why you're using them. Use of global variables leads to "spooky action at a distance" problems such as the one pointed out by state-o-dis-array. Better (lexical variable, no chomp, no prototype):

    sub add_iLO3_data { my $str = "Memory (a whole buncha stuff) "; ... }

      I read the article you suggested and I removed the prototypes, thank you very much for linking that article!

      The second issue is minor, since I modified the script just enough to show you the useful part. Actually I was using readpipe, so I had the newline at end and no manual assignment of $_

Re: Wrong content of variable passed to sub
by jwkrahn (Monsignor) on Aug 21, 2013 at 04:53 UTC
    my @fields = split(/\|/); my $name = $fields[0]; $name =~ s/\s*//; $name =~ s/\s*$//; my $value = $fields[1]; $value =~ s/\s*//; $value =~ s/\s*$//; my $status = $fields[3]; $status =~ s/\s*//; $status =~ s/\s*$//;

    That should be:

    my ( $name, $value, undef, $status ) = split /\|/; s/^\s+//, s/\s+$// for $name, $value, $status;
      I implemented your suggestion too, thanks!

Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://1050262]
Approved by state-o-dis-array
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others contemplating the Monastery: (11)
As of 2014-07-11 03:48 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    When choosing user names for websites, I prefer to use:








    Results (218 votes), past polls