Search code examples
perlcommand-line-argumentsargvstring-interpolation

How do I assign an element of @ARGV to a $variable, then print it?


It has been frequently asked in various ways, however, I am going to ask again because I do not fully comprehend the application of @ARGV and because I have not found an answer to this issue (or, more likely, I do not understand the answers and solutions already provided).

The question is, why is nothing being read from the command-line? Also, how do I decrypt the error message,

Use of uninitialised value $name in concatenation (.) or string at ... ?

I understand that @ARGV is an array that stores command-line arguments (files). I also understand that it can be manipulated like any other array (bearing in mind index $ARGV[0] is not the same as the command-line feature of filename variable, $0). I understand that when in a while-loop, the diamond operator will automatically shift the first element of @ARGV as $ARGV[ ], having read a line at input.

What I do not understand is how to assign an element of @ARGV to a scalar variable and then print the datum. For example (code concept taken from Learning Perl),

my $name = shift @ARGV;

while (<>) {
    print “The input was $name found at the start of $_\n”;
    exit;
}

As the code stands, $name’s output is blank; were I to omit shift(), $name would output 0, as I believe it should, being in scalar context, but it does not answer the question of why input from the command-line is nor being accepted. Your insights will be appreciated.

Thank you.


Solution

  • my $name = shift @ARGV; does indeed assign the program's first argument. If you get Use of uninitialised value $name in concatenation (.) or string at ..., it's because you didn't provide any arguments to your program.

    $ perl -we'my $name = shift(@ARGV); print "My name is $name.\n"'
    Use of uninitialized value $name in concatenation (.) or string at -e line 1.
    My name is .
    
    $ perl -we'my $name = shift(@ARGV); print "My name is $name.\n"' ikegami
    My name is ikegami.
    

    There's absolutely no problem with using <> afterwards.

    $ cat foo
    foo1
    foo2
    
    $ cat bar
    bar1
    bar2
    
    $ perl -we'
       print "(\@ARGV is now @ARGV)\n";
       my $prefix = shift(@ARGV);
    
       print "(\@ARGV is now @ARGV)\n";
       while (<>) {
          print "$prefix$_";
          print "(\@ARGV is now @ARGV)\n";
       }
    ' '>>>' foo bar
    (@ARGV is now >>> foo bar)
    (@ARGV is now foo bar)
    >>>foo1
    (@ARGV is now bar)
    >>>foo2
    (@ARGV is now bar)
    >>>bar1
    (@ARGV is now )
    >>>bar2
    (@ARGV is now )