Re: <> to read command line options?
by kcott (Archbishop) on Aug 16, 2013 at 02:51 UTC
|
G'day slackcub,
Welcome to the monastery.
I don't own that book; however, for those that do, it would have been helpful to identify where in the book that one line of code exists.
I expect that the book is talking about reading the contents of files whose filenames occur on the command-line.
Given this file:
$ cat pm_1049671_temp.txt
a b c
d e f
g h i
Here's what I think the book is trying to explain:
$ perl -Mstrict -Mwarnings -le '
my @numbers;
push @numbers, split while <>;
print "@numbers";
' pm_1049671_temp.txt
a b c d e f g h i
You can have more than one filename on the command-line. Here's another file:
$ cat pm_1049671_2temp.txt
j k l
m n o
p q r
Here's the same code reading the contents of both files:
$ perl -Mstrict -Mwarnings -le '
my @numbers;
push @numbers, split while <>;
print "@numbers";
' pm_1049671_temp.txt pm_1049671_2temp.txt
a b c d e f g h i j k l m n o p q r
The actual command-line arguments are available to your program in the @ARGV array:
$ perl -Mstrict -Mwarnings -le '
print "@ARGV";
' pm_1049671_temp.txt pm_1049671_2temp.txt
pm_1049671_temp.txt pm_1049671_2temp.txt
Here's some further reading that may be helpful to you:
-
perlop: I/O Operators — I suggest you read the introductory paragraphs (for background information) and then, a little further down, you'll find "The null filehandle <> is special: ..." which relates directly to your current issue.
-
perlvar: Variables related to filehandles — Again, read the introductory information then, further down, find $ARGV, @ARGV, ARGV and ARGVOUT; $. (a little after those) also has relevant information.
-
perlrun — This has useful information regarding command-line usage; search for "<>" and "ARGV" to find items related to your question. There's information about other ways to deal with filenames on the command-line: I'll leave you to reseach this yourself.
| [reply] [d/l] [select] |
Re: <> to read command line options?
by 2teez (Vicar) on Aug 16, 2013 at 08:21 UTC
|
slackcub wrote:..They use that to read they list of arguments **from the command line...
That is not SO! Sir!! :). I suppose you presumed that. Reading from the explanation of solution given by the author(s) of the book on that exercise:
That second line of code is too confusing *(that is referring to push @numbers, split while <>;), isn’t it? Well, we did that on purpose. Although we recommend that you write clear code, some people like writing code that’s as hard to understand as possible, so we want you to be prepared for the worst. Someday, you’ll need to maintain confusing code like this.
Since that line uses the while modifier, it’s the same as if it were written in a loop
like this:while (<>) {
push @numbers, split;
}
That’s better, but maybe it’s still a little unclear. (Nevertheless, we don’t have a
quibble about writing it this way. This one is on the correct side of the “too hard
to understand at a glance” line.) The while loop **is reading the input one line at a
time (from the user’s choice of input sources, as shown by the diamond operator),
and split is, by default, splitting that on whitespace to make a list of words—or
in this case, a list of numbers. The input is just a stream of numbers separated by
whitespace, after all. Either way you write it, then, that while loop will put all of
the numbers from the input into @numbers.
NOTE:
* included by me for clarity.
** Bold text were used for emphasis.
If you tell me, I'll forget.
If you show me, I'll remember.
if you involve me, I'll understand.
--- Author unknown to me
| [reply] [d/l] [select] |
Re: <> to read command line options?
by Anonymous Monk on Aug 16, 2013 at 02:20 UTC
|
| [reply] |
|
|
oh, I figured they should have used @ARGV, but this is a quote from them in the answer:
my @numbers;
push @numbers, split while <>;
foreach (sort { $a <=>$b } @numbers) {
printf "%20g\n", $_;
}
then later in the explanation of the answer:
The while loop is reading the input one line at a time (from the user’s choice of input sources, as shown by the diamond operator), and split is, by default, splitting that on whitespace to make a list of words—or in this case, a list of numbers. The input is just a stream of numbers separated by whitespace, after all. Either way you write it, then, that while loop will put all of the numbers from the input into @numbers.
The instructions in the exercise are:
Write a program to read in a list of numbers and sort them numerically
+, printing out the resulting list in a right-justified column. Try it
+ out on this sample data:
17 1000 04 1.50 3.14159 –10 1.5 4 2001 90210 666
unless I'm reading it wrong and they actually wanted it in a file. I was assuming it was supposed to be as command line options. That's certainly possible, as I'm still new to all this! ;} | [reply] [d/l] [select] |
|
|
Yes, it does want the numbers as a file, rather than as command line arguments. If you make a numbers.txt file with all the numbers, then use numbers.txt as the only argument to your program, it does what it's supposed to.
The diamond operator <> lets you choose what to use for input in the arguments to your program. When you leave it empty, it will wait for user input. With a program like this one, it doesn't tell you that it's waiting for something, which was surprising when I did this exercise myself a couple of months ago :)
| [reply] [d/l] [select] |
Re: <> to read command line options?
by ww (Archbishop) on Aug 16, 2013 at 02:34 UTC
|
Can you give us a reference (page, edition) for the code you showed (without using <c>...code here... </c> code tags; for shame. Read instructions at the SOPW text-entry box.) And check the O'Reilly site for reports of typos and corrections to whichever edition you're using.
I suspect there's either a typo or a prior discussion of capturing from STDIN, "Standard In," AKA "the console." If you follow your code at the command line with numbers, hoping that will feed them to split and @numbers the disappointment you specify will occur. But you'll get the expected results if you collect the user's numbers like this:
C:\>perl -E "print 'your input please: ' ; my $input = <>; say $input;
+"
your input please: 1 2 32
1 2 32
And, with the syntax you showed:
C:\>perl -E "print 'Enter nums: '; use Data::Dumper;@numbers; push @nu
+mbers, split while <>; say Dumper @numbers;"
Enter nums: 3 5 7 912 11
^Z
$VAR1 = '3';
$VAR2 = '5';
$VAR3 = '7';
$VAR4 = '912';
$VAR5 = '11';
If I've misconstrued your question or the logic needed to answer it, I offer my apologies to all those electrons which were inconvenienced by the creation of this post.
| [reply] [d/l] [select] |
|
|
6th edition (epub from O'Reilly), page 390, chapter 14 example answers. I looked at the errata on O'Reilly's website and didn't see any mention of it. I'll have to do some looking around.
And I apologize for my misuse of <c>. I guess I'm used to using it when quoting anything on other forums.
| [reply] |
|
|
| [reply] |
Re: <> to read command line options?
by Anonymous Monk on Aug 16, 2013 at 14:18 UTC
|
Nobody has said it clearly yet. perlop:
The null filehandle <> is special: it can be used to emulate the
behavior of sed and awk. Input from <> comes either from standard
input, or from each file listed on the command line. Here's how it
works: the first time <> is evaluated, the @ARGV array is checked, and
if it is empty, $ARGV[0] is set to "-", which when opened gives you
standard input. The @ARGV array is then processed as a list of
filenames. The loop
while (<>) {
... # code for each line
}
is equivalent to the following Perl-like pseudo code:
unshift(@ARGV, '-') unless @ARGV;
while ($ARGV = shift) {
open(ARGV, $ARGV);
while (<ARGV>) {
... # code for each line
}
}
| [reply] |