•Re: Testing <> for undefined
by merlyn (Sage) on Jul 07, 2004 at 16:30 UTC
|
If you're asking how to see if there are command line arguments, the arguments are copied into @ARGV. Check the length of that array. If it's empty, then you have no args:
if (@ARGV) {
# you have command line args
} else {
# ya don't!
}
| [reply] [d/l] |
Re: Testing <> for undefined
by dws (Chancellor) on Jul 07, 2004 at 16:30 UTC
|
Your best bet is to put input into a variable, and test from here. That avoids icky little "but I didn't mean to read twice!" bugs. Also, direct comparisons are going to be problematic unless you remove the trailing newline that comes with the input. E.g.,
my $input = <>;
chomp($input); # remove trailing \n
if ( $input eq "" ) { ... }
But none of that helps when you need to be looking at @ARGV instead.
| [reply] [d/l] [select] |
Re: Testing <> for undefined
by gellyfish (Monsignor) on Jul 07, 2004 at 16:36 UTC
|
You don't want to test the diamond operator, you want to test whether any command line arguments were supplied:
if ( @ARGV == 0 )
{
print "Something useful\n";
}
/J\ | [reply] [d/l] |
Re: Testing <> for undefined
by Joost (Canon) on Jul 07, 2004 at 16:31 UTC
|
| [reply] |
Re: Testing <> for undefined
by Roy Johnson (Monsignor) on Jul 07, 2004 at 16:32 UTC
|
Command line arguments are in the array named @ARGV. The diamond operator gets lines from whatever the current input file is.
If you get a line from a file and test it as in your examples, you will no longer have that line to play with. You want to fetch it into a variable and then do your tests, etc.
We're not really tightening our belts, it just feels that way because we're getting fatter.
| [reply] [d/l] |
Re: Testing <> for undefined
by TrekNoid (Pilgrim) on Jul 07, 2004 at 16:46 UTC
|
Here's something that I use in most of my scripts:
Assuming the scriptname is called file_parse.pl, and you're trying to pass it single file only:
if ($#ARGV != 0) {
print "Usage: file_parse.pl [filename] \n";
exit(1);
}
Trek | [reply] [d/l] |
|
| [reply] |
|
My rule is, use @ARGV when you want to talk about the number of elements, and reserve $#ARGV for getting the ending index for ranges.
Thanks, merlyn... It's one of those things I learned to do one way when I was first learning Perl, and have never gone back and revisted it...
There's just so few things I can help people with in Perl, that I get excited when I see one I *can* answer :) Guess I'm destined to remain an acolyte for the foreseeable future :)
I'll make a note for future development
Trek
| [reply] |
Re: Testing <> for undefined
by danielcid (Scribe) on Jul 08, 2004 at 13:46 UTC
|
You could also do something like that:
# Test if the is an argument
if(!@ARGV)
{
die "My help message\n";
}
# Test if the argument is a file
if(! -e $ARGV[0])
{
print "File $ARGV[0] does not exist\n";
}
[]'s
-DBC
Edited by Chady -- code tags, escaped a [ | [reply] [d/l] |
Re: Testing <> for undefined
by danielcid (Scribe) on Jul 08, 2004 at 15:59 UTC
|
*fixing my previous post:
You could also do something like that:
# Test if the is an argument
if(!@ARGV)
{
die "My help message\n";
}
# Test if the argument is a file
if(! -e $ARGV[0])
{
print "File $ARGV0 does not exist\n";
}
's -DBC | [reply] [d/l] |
|
I have done this in the past, and it seems to work fine:
my $file = $ARGV[0] ? $ARGV[0] : die "USAGE: prog.pl file_pathname\n";
open(FILE,"$file") or die "Unable to open file $file\n"; | [reply] |
|
I have to say that I hate your use of the trinary operator there. You're expressing that you want to assign die's result to $file. Instead:
my $file = $ARGV[0] or die "Usage: prog.pl file_pathname\n";
(as a bonus, you don't have the redundant mention of $ARGV[0]).
Better, if the filename might be zero:
@ARGV or die "Usage: prog.pl file_pathname\n";
my $file = $ARGV[0];
We're not really tightening our belts, it just feels that way because we're getting fatter.
| [reply] [d/l] [select] |
Re: Testing <> for undefined
by graff (Chancellor) on Jul 08, 2004 at 23:38 UTC
|
Here's something that is relevant to your question, but has not been explained yet in the other replies that I read. Part of the magic of while (<>) is that it will handle all of the following types of command line usage:
# name one file:
my_script.pl input.file
# name multiple files:
my_script.pl first.file second.file ...
# use redirection from a file to STDIN:
my_script.pl < some.file
# use a pipeline to STDIN:
other_process | my_script.pl
# e.g.:
cat *.file | my_script.pl
That is, if one or more files are named as args to the script, a while (<>) loop will step through and read each file in turn. On the other hand, if data is being fed to the script on its STDIN (via redirection or pipeline), while (<>) will read that.
(The default behavior does not let you do both: if files are named as args, the plain, empty diamond operator reads the files and does not read STDIN.)
Anyway, the reason why you have to check @ARGV first, and not test the diamond operator, is that when @ARGV is empty, the script will wait until there is either input data (i.e. one whole line) or an EOF condition on STDIN, and you won't be able to check the result of the diamond operator until one of those things happens. | [reply] [d/l] [select] |
Re: Testing <> for undefined
by jdavidboyd (Friar) on Jul 10, 2004 at 00:11 UTC
|
Okay, here's something I don't understand.
Suppose I have the following code, I'll call it prog.pl:
#!/usr/bin/perl
my $lines;
my @lines;
print ("\@ARGV: @ARGV, \$\#ARGV: $#ARGV\n");
if (!@ARGV){
print("No command line parameters present");
}
chomp(@lines = <>);
foreach $lines (@lines){
print("$lines\n");
}
1. If I run the program as perl prog.pl test.txt it prints out
@ARGV: test.txt, $#ARGV: 0
2. If I run the program as perl prog.pl it prints out
@ARGV: , $#ARGV: -1
(This next one is my problem.)
3. If I run the program as perl prog.pl < test.txt it prints out
@ARGV: , $#ARGV: -1
which looks as if there were no command line arguments.
Now, I realize that in some aspects, this might be considered correct, as there are no command line arguments, just input to the <> operator.
Will GetOpt get around this peculiarity?
Or am I going to be stuck always showing my little help text no matter what?
Am I missing something dreadfully obvious?
| [reply] [d/l] |
|
When you invoke the perl interpreter (i.e. "perl") on the command line, and give it the name of a script file to load and execute, then any command-line args that follow the name of the script file are passed directly to the script as the contents of @ARGV. If nothing follows the name of the script file, then the script gets an empty @ARGV.
If the script file itself is treated by the shell/OS as an executable file, so that the name of the script file can be the first thing on the command line, the behavior is the same: any args following the name of the script file are provided to the script in @ARGV.
Of course, if the things that follow the script name happen to have special meaning to the shell, like a redirection operator (< or >), logic/process-control operator (& or vertical bar), or other things (depending on your shell), then the shell will do what it is supposed to do with such args before working out the strings to be passed to your script as @ARGV.
So in a command like myscript.pl < my.input (or the version that uses "perl" at the beginning), the angle bracket and the arg after it are treated by the shell as things to be handled by the shell, and these are not passed on to the perl script's @ARGV. This is why, if your script is set up to accept args that contain such characters, you need to quote or escape them on the command line, so that the shell will pass them to the script verbatim rather than acting on them itself.
| [reply] [d/l] |
|
Ah, thank you very much.
I hypothetically knew this, but I had never really internalized it.
Thanks for the explanation!
| [reply] |