Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations John Tel on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Unix, perl, @argv HELP 1

Status
Not open for further replies.

ernieah

Programmer
Oct 27, 2002
42
US
(1) How does one "pass two parameters" to any perl script,
by enterning the parameters on the "command line", where one (either one) is a filename, and the other is some variable-value to be passed to a variable-name in the perl script)?

I had supposed (from my reading in perl books)that the array, "@ARGV" held all the "parameters" on the "command line". However, when I try this, I get confusing (to me) results, and certainly not the results I expected!

(2) Example #1:
script:
==========================================================
# program perl_argv_1.pl

print '@ARGV[0] = ', @ARGV[0], "\n";
print '@ARGV[1] = ', @ARGV[1], "\n";
==========================================================
command-line: &quot;perl perl_argv_1.pl sample sample_2 <enter>&quot;
===========================================================
Output:

@ARGV[0] = sample
@ARGV[1] = sample_2
============================================================My comment: This is what I understood would happen, and what I expected to happen - no problem. But the next program, &quot;perl_argv_2.pl&quot; does NOT produce the results I expected;
-----------------------------------------------------------
-----------------------------------------------------------
Example #2
script:

# program perl_argv_2.pl

print '@ARGV[0] = ', @ARGV[0], &quot;\n&quot;;
print '@ARGV[1] = ', @ARGV[1], &quot;\n&quot;;

while ( <sample> )
{ print $_; }
===========================================================
command-line: &quot;perl perl_argv_2.pl sample sample_2 <enter>&quot;
===========================================================
output:

@ARGV[0] = sample
@ARGV[1] = sample_2
============================================================
My comment: This is certainly NOT what I expected. I thought the program would print the first two lines (above), and then in addition, all the lines of the ascii-text-file, &quot;sample&quot;, following the above two lines!
============================================================ Example #3:
Script:

# program perl_argv_3.pl

print '@ARGV[0] = ', @ARGV[0], &quot;\n&quot;;
print '@ARGV[1] = ', @ARGV[1], &quot;\n&quot;;
print &quot;-------------------------\n&quot;;
while ( <@ARGV[0] > )
{ print $_; }
============================================================
command-line: &quot;perl perl_argv_3.pl sample sample_2 <enter>&quot;
===========================================================
Output:
@ARGV[0] = sample
@ARGV[1] = sample_2
-------------------------
sample
==========================================================
My comment: I'm not sure what I expected. What I WANTED was the program to print the first two lines and then, following that, the CONTENT of the file: &quot;sample&quot;. I understand (I think), why I got the result I did, even though it wasn't the results I wanted.
===========================================================
Example #4
Script:

# program perl_argv_4.pl

print '@ARGV[0] = ', @ARGV[0], &quot;\n&quot;;
print '@ARGV[1] = ', @ARGV[1], &quot;\n&quot;;
print &quot;-------------------------\n&quot;;
while ( <> )
{ print $_; }

============================================================
command-line: &quot;perl perl_argv_4.pl sample sample_2 <enter>&quot;
===========================================================
Output:
@ARGV[0] = sample
@ARGV[1] = sample_2
-------------------------
sample
123 mary has fair skin
has red hair
1286 bob has no
hair



sample
XXX123 mary has fair skin
has red hair
XXX1286 bob has no
hair
=========================================================
My comment: This is exactly what I expected from my commmand line - but NOT what I wanted. What I WANTED was to print the CONTENTS of the file: &quot;sample&quot;, and to use the 2nd. command-line parameter (&quot;sample_2&quot;) for &quot;SOMETHING ELSE&quot; (whatever else doesn't particularly matter.)

The question is: HOW do I &quot;tell&quot; perl that one (either one) of these two parameters is a file name, and the other is merely one of the values of &quot;@ARGV&quot;?

I had expected that Example#3 would do this, since I had &quot;spelled-out&quot; (I thought) the &quot;name&quot; of the file I wanted to read and print (as the VALUE &quot;contained in&quot; @ARGV[0]), and I had NOT mentioned reading and printing the &quot;other&quot; file, &quot;sample_2. Instead,, of course, as one can see, I did NOT print out the contents of either file, in Example#3, as I had wanted to do with ONE of them.
===========================================================================================
The question is: HOW do I &quot;tell&quot; perl that one (either one) of these two parameters is a FILE NAME, to be READ and &quot;processsed&quot;, and the other is merely one of the values of &quot;@ARGV&quot; that I want to use some (any) other way?
=========================================================================================
Thanx in advance for any help you can give me with this. ernieah
 
Hi ernieah,

You could try using a filetest against @ARGV. If it evaluates true the parameter is a valid file and you can then use the
Code:
open
function on it. You'll want to read up on that if you haven't yet. That's how you'll get your script to print out the contents of the file.

If the filetest (-e) evaluates false, either you mistyped the filename and/or directory, or it's the other parameter(s) you're looking for. Example:

Code:
foreach ( @ARGV ) {
  if ( -e $_ ) {
    open SAMPLE, $_ or die &quot;Couldn't open $_ file: $!\n&quot;;
    while ( <SAMPLE> ) { print; }
    close SAMPLE;
  } else {
    #do stuff if not a valid file
  }
}

You were close with your &quot;while (<sample>)&quot; bit, as you were reading from a filehandle. But you first have to open the file for this to work as in the example above.

There's probably a better way to sort out what is and what is NOT a file in @ARGV and what IS a general parameter, but I don't have it. [wink]

[hth] Notorious P.I.G.
 
=============================================
Example #5: To: PerlIsGood, From: ernieah,
29-Oct-2002.

Thanx very much for your prompt and
responsive reply! I tried the &quot;file open&quot; gambit
you suggested on (only) ONE of the
command-line-parameters.

However, for some reason, I am still having the
problem of printing either BOTH of the command-line-parameter files, or
NEITHER of them.
=============================================
Script:
Code:
#!/usr/bin/perl
# Program: &quot;play_argv_practice&quot;
# Purpose: practice use of: argv
# ------------------------------------
print '@ARGV[0] = ',  @ARGV[0], &quot;\n&quot;;
print '@ARGV[1] = ',  @ARGV[1], &quot;\n&quot;;
open ( TEXT1, &quot;< @ARGV[0]&quot;) ||  die &quot;Can't open file: @ARGV[0]\n&quot;;
print &quot;--------------------------\n&quot;;

while  (  < TEXT1 >   ) 
       {  print $_;        } 

print &quot;\n&quot;;
print &quot;--------------------------\n&quot;;
close TEXT1;
=============================================
Command-line:
./play_argv_practice sample_1 sample_2 <enter>
=============================================Output:

@ARGV[0] = sample_1
@ARGV[1] = sample_2
--------------------------
TEXT1
-------------------------
=============================================
My comment: This variation printed the contents
of NEITHER of the two command-line-parameter
files, even though I HAD (successfully) &quot;opened&quot;
the ONE of them that I wanted to print.
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Example#6
Script:
Code:
#!/usr/bin/perl
# Program: &quot;play_argv_practice_2&quot;
# Created\Latest update: 29-Oct-2002
#
# ------------------------------------
print '@ARGV[0] = ',  @ARGV[0], &quot;\n&quot;;
print '@ARGV[1] = ',  @ARGV[1], &quot;\n&quot;;
open ( TEXT1, &quot;< @ARGV[0]&quot;) ||  die &quot;Can't open file: @ARGV[0]\n&quot;;
print &quot;--------------------------\n&quot;;

while  (  <>   ) 
       {  print $_;        } 

print &quot;\n&quot;;
print &quot;--------------------------\n&quot;;
close TEXT1;
=============================================
Command-line:
./play_argv_practice_2 sample_1 sample_2 <enter>
=============================================
Output:

@ARGV[0] = sample_1
@ARGV[1] = sample_2
--------------------------
(1) Line-1: I like green ham.
(2) Line-2: Sam I am.

Line-1: This is file: &quot;sample_2&quot;.
Line-2: another line.
Line-3: a third line.


--------------------------
=============================================
My comment: Here I got BOTH of the
command-line-parameter files printed out,
even though I had (explicity) &quot;opened&quot; only ONE
of them. Of course, I only wanted to print ONE
of them.

Again, any thoughts you have on this
would be greatly appreciated,
as I still haven't &quot;got the hang of it&quot;. (It's
always &quot;easy&quot;, from then on, when you've
&quot;got it&quot;, like: &quot;The rain in Spain..&quot;

Thanx again!
=============================================
 
=======================================
Example #7 Eureka! Finally a way
to do it!

(7a) After trying lots of &quot;other&quot; ways,
I was &quot;forced&quot; (from desperation)
to look for some other way to send
command-line-parameters to a perl
script, and distinguish between those
parameters which are filenames, and those
which are anything\something else.

(7b) I was worried all-the-way-along,
that I might have to use the &quot;dreaded
Getopt::Long&quot; ( a feared beast, since
I hadn't used Modules, yet.) Furthermore,
I was not even sure THAT would &quot;do the
job&quot;.

Finally, I felt &quot;forced&quot; to try it, even
though I had never done &quot;modules&quot; before.

(7c) The first step was putting the line:

&quot;PERL5LIB=/usr/lib/perl5/site_perl/5.005/i386-linux; export PERL5LIB&quot;

into my &quot;.profile&quot; file, on my Unix workstation.
This tells perl where to find the &quot;modules&quot;.
Else a statement like: &quot;use Getopt::long;&quot; won't work,
since perl will not know where to find the
&quot;Getopt::Long&quot; module.

(7d) Then, I can &quot;set up&quot; a sort of definition
(using the features of Getopt::Long) of my
command-line-parameters-which-are-NOT-file-names,
with the default that any OTHER (left over?)
filenames on the command line will ACTUALLY
be file-names (rather than something else).

Example #7

Script:

Code:
#!/usr/bin/perl 
# Program: &quot;play_argv_practice_3&quot;
# Original Programmer: ernie brown
# Created\Latest update: 29-Oct-2002
#
# ------------------------------------
use Getopt::Long;

GetOptions(&quot;look_for=s&quot;    => \$look_for);

print &quot;\$look_for = &quot;, $look_for, &quot;\n&quot;;

open (TEXT1, &quot;< $input_file&quot;) || die &quot;Can't open file: $input_file: $!\n&quot;;

print &quot;--------------------------\n&quot;;

while  (  <>                ) 
       {  print $_;         } 

print &quot;\n&quot;;
print &quot;--------------------------\n&quot;;
close TEXT1;
=====================================
Command-line:
./play_argv_practice_3 --look_for=&quot;I like green ham&quot; sample_1 <enter>
====================================
Output:

$look_for = I like green ham
--------------------------
(1) Line-1: I like green ham.
(2) Line-2: Sam I am.


--------------------------
====================================]
My comment: Here, i am &quot;defining&quot; a
command-line-parameter, &quot;$look_for&quot;,
using the GetOptions function (a part of
the Getopt::Long module). In such cases,
after one defines such a &quot;multi-character&quot;
parameter, the user puts two consecutive
dashes immediatelly to the left of
the &quot;parameter name&quot;, which MUST also
appear on the command-line, followed by an
equals-sign, followed by the ACTUAL-value
of the &quot;multi-character&quot; parameter. I HAVE
to use double-quotes to set-off the
&quot;multi-word&quot; parameter, since it has spaces
&quot;embedded between' each of the words.

In the above case:
--look_for=&quot;I like green ham&quot;

appears on the command-line.

as, you can see.


In my example #7, I simple PRINT the
value of the &quot;look_for&quot; command-line
parameter, from within the script.
A user could do other things with it.

Then, of couse, I print the CONTENT of
the &quot;left-over&quot; parameter (no --,
no parmeter-NAME, no equals sign),
sample_1, which IS an actual file-name,
which you can also see on the
command line.

(7E) Enough for now. Thanks again to
PerlIsGood, for helping me along the way!
best to you from ernieah:
ernestcbrown@earthlin.net
Ernest.Brown@noaa.gov
=====================================



 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top