Re: Trying to make a search
by mdillon (Priest) on Jun 03, 2000 at 22:27 UTC
|
the value of $letter has a line ending on the end. try this:
print "Letter? ";
my $input = <STDIN>;
# get rid of line ending
chomp($input);
# take the first character and escape it if it is a possible metachara
+cter
my $letter = quotemeta substr $input, 0, 1;
open DATA, 'books.txt' or die "Couldn't open books.txt: $!";
my @data = <DATA>;
close DATA;
foreach my $data (@data)
{
print $data if $data =~ /^$letter/i;
}
| [reply] [d/l] |
Re: Trying to make a search
by lhoward (Vicar) on Jun 03, 2000 at 23:17 UTC
|
There are several problems with your code... As mdillon already
pointed out you should chomp $input to remove the
cr/lf. The other major error is in the following line:
print "${line}";
That should read $line and not ${line}.
Now I've fixed your code (you can see my fixes below) to make it
functional, but it still isn't very "perl" looking and has
some needless code.
#!/usr/bin/perl
my $ans;
my $currentline;
my @data;
print "Letter? ";
$letter = <STDIN>;
chomp $letter;
open (DATA, "books.txt");
@data = <DATA>;
$currentline = 0;
foreach $data(@data) {
$line = $data[$currentline]; # there are brackets around $cu
+rrentline
if ($line =~ /^$letter/i) {
print $line;
}
$currentline++
}
Now here is a much more "perl-looking" implementation:
#!/usr/bin/perl -w
use strict;
print "Letter? ";
my $letter = <STDIN>;
chomp $letter;
open (DATA, "books.txt") or die "error opening file $!";
my $line;
foreach $line(<DATA>) {
if ($line =~ /^$letter/i) {
print $line;
}
}
close DATA;
| [reply] [d/l] [select] |
|
|
hehe, on the idea of more "perl looking", in my opinion:
#/usr/bin/perl -w
use strict;
print "Letter: ";
chomp(my $letter = <STDIN>);
open(DATA, "books.txt") or die "error opening file $!";
while(<DATA>) {
if (/^$letter/i) {
print;
}
}
charlie schmidt
ishamael@themes.org
www.diablonet.net/~ishamael/
| [reply] [d/l] |
|
|
Since we're already picking nits and playing reductionists;
here's removing a little more redundancy. Hopefully without
crossing over and becoming obscure (versions involving
map()/grep()-combos deliberately left as an excersice for
the reader ;D)
#!/usr/bin/perl -w
use strict;
print "Letter? ";
my $letter = <STDIN>;
chomp $letter;
open DATA, "books.txt" or die "open(books.txt) returned: $!\n";
foreach my $line (<DATA>) {
print $line if $line =~ /^$letter/i;
}
close DATA;
| [reply] |
|
|
Grep is not obscure. It is much clearer than dumb loops
that are really just low level implementations of list
operations.
#!/usr/bin/perl -w
use strict;
print "Letter? ";
chomp(my $letter = <STDIN>);
open DATA, "books.txt"
or die "open(books.txt) returned: $!\n";
print grep {/^$letter/io} <DATA>;
Of course, I kind of like something like
perl -e 'print grep {/^a/io} <>' /usr/dict/words
Try it, you'll like it too! | [reply] [d/l] [select] |
|
|
> The other major error is in the following line:
><BR
> print "${line}";
>
> That should read $line and not ${line}.
Actually, it doesn't make a difference. ${line} is just as
good (and sometimes better) as $line in double-quotish contexts.
| [reply] [d/l] |
Re: Trying to make a search
by takshaka (Friar) on Jun 04, 2000 at 05:45 UTC
|
This thread has gotten out of hand;
but as long as we're going for Perlishly obscure,
here's something silly...
#!/usr/bin/perl -wp
use strict;
use vars '$letter';
s/^(?!\Q$letter\E).*//is;
BEGIN {
@ARGV = 'books.txt';
print 'Letter: ';
chomp($letter = <STDIN>);
}
| [reply] [d/l] |
Re: Trying to make a search
by Anonymous Monk on Jun 04, 2000 at 05:12 UTC
|
As long as we're going for perl looking, we might as well go for obscure...
#/usr/bin/perl -w
use strict;
print "Letter: ";
chomp(my $letter = <STDIN>);
open(DATA, "books.txt") || die "error opening file $!";
while(<DATA>) {
(/^$letter/i) && print;
}
| [reply] [d/l] |
|
|
Please, before posting, read the
guidelines and use a
</{0,1}CODE> tags around your code,
or else it will look like the above, which is not
valid perl. For those curious, the poster meant for a
<STDIN> to appear in the "chomp" line, and
the while line to say while(<DATA>) {
P.S. I think that
print if /$letter/i;
is shorter and a bit clearer.
| [reply] [d/l] |
RE: Trying to make a search
by turnstep (Parson) on Jun 04, 2000 at 19:15 UTC
|
open(DATA, "books.txt" or die "Could not open file: $!\n";
print "Letter: " and chomp (my $letter=<STDIN>);
while(<DATA>) { print if /^$letter/io; }
Note: mdillon is correct below: the ^ was added after his
comment.
| [reply] [d/l] |
|
|
this won't fulfill the original author's requirement of
matching lines that _begin_ with a certain letter. you're
missing the '^' at the beginning of your regular expression.
also, why does everyone but me just assume in their
solution that user will be well-behaved and only enter
a single letter? i know we're not writing production code
here, but it seems a little odd to me that i was the only
one to bother to do 'substr $input, 0, 1'.
one thing i liked that no one else remembered to do was
turnstep's use of the 'o' regular expression modifier to
only compile the regexp once.
| [reply] |
|
|
also, why does everyone but me just assume in their solution that user will be well-behaved
and only enter a single letter? i know we're not writing production code here, but it seems a
little odd to me that i was the only one to bother to do 'substr $input, 0, 1'.
Perhaps it is a bleed-over of Perl's DWIM concept.
It seems logical (to me, at least)
that if the user inputs a string rather
than a single character the program should return
all lines beginning with that string. But then I imagine
it is just as logical to you that the program should
only use the first character as the search prefix.
In legitimate production code
where we are concerned about how many characters
the user inputs, it would probably be better to allow
only one character--rather than an entire line--to be
input in the first place (don't want to confuse those
end-users). And since the OP does say 'letter',
we'd also reject any input that isn't one.
| [reply] |