Forcing list context on <$fh>

A

A. Farber

Hello,

I have a CGI-script for creating new users.
You can either upload a CSV file for a batch
of users or fill out a web for for just 1 user.

So I have a ref to array which contains
either lines from the uploaded CSV file or
just 1 line constructed from the web form:

my $input = $fh ? [ <$fh> ] :
# trick: create a line as if a Lotus Notes CSV-file has
been uploaded
[ sprintf '%s;%s;;;%s;XXX;%s;;;XXX;%s-%s;;%s%s.
%[email protected];;XXX;;;;%s;',
$QUERY->param('last'),
$QUERY->param('first'),
$QUERY->param('pass'),
$QUERY->param('user'),
$QUERY->param('company'),
$QUERY->param('city'),
($QUERY->param('company') =~ /^mycompany$/i ? '' :
'ext-'),
$QUERY->param('first'),
$QUERY->param('last'),
($QUERY->param('inform') =~ /nobody/i ? '' : $QUERY-
param('inform')) ];

my $loh = validate_input($input);

My problem above is that [ <$fh> ] seems
to be evaluated in a scalar context and
I get just 1 line instead of all.

Is there a nice way to force list context on it?

Thanks
Alex
 
T

Tad J McClellan

A. Farber said:
So I have a ref to array which contains
either lines from the uploaded CSV file or
just 1 line


The 2nd case is not a "line" since it does not have a newline in it...

constructed from the web form:

my $input = $fh ? [ <$fh> ] :

$QUERY->param('last'),
$QUERY->param('first'),
$QUERY->param('pass'),
$QUERY->param('user'),
$QUERY->param('company'),
$QUERY->param('city'),


If you put the params into a hash then you can use a "hash slice"
to get the values you want in one go:


my %Q = $QUERY->Vars;

sprintf ... , @Q{ qw/ last first pass user company city / };

($QUERY->param('company') =~ /^mycompany$/i ? '' :
'ext-'),


A test for equality should *look like* a test for equality:

lc($Q{company}) eq 'mycompany' ? '' : 'ext-';


BTW, there are *two* strings that will match /^mycompany$/
(so it isn't really an equality test...).

Do you know what the two possible matching strings are?


My problem above is that [ <$fh> ] seems ^^^^^
to be evaluated in a scalar context and


Find out what context it is in for sure rather than guessing:

sub context {
if ( wantarray )
{ warn "list\n" }
else
{ warn "scalar\n" }
}

my $input = $fh ? [ context() ] : ...

I get just 1 line instead of all.

Is there a nice way to force list context on it?


There is no way to "force" list context like there is for scalar context.

To get a list context, you use it in a place where a list is expected,
such as inside of an anonymous array constructor.

The source of your problem must be somewhere else...
 
S

smallpond

My problem above is that [ <$fh> ] seems
to be evaluated in a scalar context and
I get just 1 line instead of all.

perl -e 'open FH,"<wbtest.pl"; $r= FH ? [ <FH> ] : []; print $#
$r,"\n"'
180

works fine
 
P

Peter J. Holzer

A test for equality should *look like* a test for equality:

lc($Q{company}) eq 'mycompany' ? '' : 'ext-';


BTW, there are *two* strings that will match /^mycompany$/
(so it isn't really an equality test...).

And there are 1024 strings which will match /^mycompany$/i, which will
make it even less of an equality test :).

hp
 
D

Dr.Ruud

Peter said:
Tad J McClellan:

And there are 1024 strings which will match /^mycompany$/i, which will
make it even less of an equality test :).

LOL. At least 1024.
 
T

Tad J McClellan

Glenn Jackman said:
Maybe I haven't had enough coffee today, but I don't know.
Please share.


-----------------------
#!/usr/bin/perl
use warnings;
use strict;

$_ = "mycompany\n";
print "matched\n" if /^mycompany$/;

$_ = "mycompany";
print "matched\n" if /^mycompany$/;
-----------------------
 
J

Jim Gibson

Glenn Jackman said:
Maybe I haven't had enough coffee today, but I don't know.
Please share.

Perhaps "mycompany" and "mycompany\n" (on certain platforms).
 
A

A. Farber

Awesome comments, thank you.

The original problem was in fact
not the list/scalar context,
but that my regex didn't match because of \x0d

(uploaded Lotus Notes CSV file in DOS format,
but the script itself runs on Linux)
 
T

Tad J McClellan

Jim Gibson said:
Perhaps "mycompany" and "mycompany\n" (on certain platforms).


On what platforms is that not true?

I thought that perl's IO layer normalized line endings, so that that
should be true on ALL platforms.
 
G

Gunnar Hjalmarsson

Ben said:
IO is irrelevant here. If you have a Perl string containing
"mycompany\n" it will match /^mycompany$/, regardless of how it ended up
with those contents.

Of course, if you read a line from an ordinary text file on Win32 with a
binmoded filehandle, the string returned will be "mycompany\r\n" and
will not match,

You don't need binmode() for that to be true.

$ cat -vE w32.txt
mycompany^M$
$ cat test.pl
open my $fh, '<', 'w32.txt' or die $!;
print <$fh> =~ /^mycompany$/ ? "Match\n" : "No match\n";
$ perl test.pl
No match
$

To make it *not* be true, i.e. to make the string match, you can binmode
the filehandle with the :crlf layer.

$ cat test.pl
open my $fh, '<', 'w32.txt' or die $!;
binmode $fh, ':crlf';
print <$fh> =~ /^mycompany$/ ? "Match\n" : "No match\n";
$ perl test.pl
Match
$
 
T

Tim McDaniel

Given that most Win32 machines don't have cat(1), and that the usual
prompt on Win32 isn't '$', I am going to presume that you are not,
in fact, running this on Win32.

MinGW and Cygwin, no matter how they perturb the environment, run
under Windows. ActiveState Perl does not, I believe, depend on
anything else, and therefore could be run equally well from cmd or a
shell.

As a practical matter, I run enough scripts on Windows (whether
under bash or cmd) and have hit the problem enough that I do
chomp;
s/\r+$//;
as a matter of rote, or instead use \s if I want to strip all trailing
whitespace whatsoever.
 
G

Gunnar Hjalmarsson

Ben said:
Given that most Win32 machines don't have cat(1), and that the usual
prompt on Win32 isn't '$', I am going to presume that you are not,
in fact, running this on Win32.

Well, obviously I misunderstood your statement. Thanks for the
clarification.
On Win32, unless you've set the PERLIO environment variable, the default
filehandle layers are ":unix:crlf".

Hmm.. I had no idea. Seems not even to be disabled by

binmode $fh, ':raw';

:(
 
G

Gunnar Hjalmarsson

Ben said:
It's been the case since long before PerlIO existed. Turning off the
default "\r\n"->"\n" conversion on Win32 is, in fact, the reason
'binmode' existed in the first place.


Have you tried it, or are you getting this from the docs?

I'm afraid that I'm guilty of a great deal of confusion, which explains
my remarks above. Please disregard them.

I thought that \n means \015\012 on Windows. Now - after having re-read
your comments, re-read the "Newlines" section in "perldoc perlport", and
played around some more - I'm slowly realizing that it means \012 just
as on *nix, and that the \015\012 newline is only used on *saved* text
files.

Suddenly everything you said in this thread makes a lot of sense, also
to me. ;-) Thanks for the lesson!
... either

binmode $fh;

or

binmode $fh, ":raw";

ought to switch the :crlf layer into a mode where it no longer does
"\r\n"->"\n" translation. I don't believe the layer actually goes away,
but it becomes exactly equivalent to a :perlio layer. Is this not
correct?

Probably. This is the test I did:

C:\home>type test.pl
open $fh, '<', 'w32.txt' or die $!;
print 'No binmode() : ',
<$fh> =~ /^mycompany$/ ? "Match\n" : "No match\n";

open $fh, '<', 'w32.txt' or die $!;
binmode $fh;
print 'binmode() without layer : ',
<$fh> =~ /^mycompany$/ ? "Match\n" : "No match\n";

open $fh, '<', 'w32.txt' or die $!;
binmode $fh, ':raw';
print 'binmode() with :raw : ',
<$fh> =~ /^mycompany$/ ? "Match\n" : "No match\n";

open $fh, '<', 'w32.txt' or die $!;
binmode $fh, ':crlf';
print 'binmode() with :crlf : ',
<$fh> =~ /^mycompany$/ ? "Match\n" : "No match\n";

C:\home>test.pl
No binmode() : Match
binmode() without layer : No match
binmode() with :raw : No match
binmode() with :crlf : Match

C:\home>

The result is the same as before, but suddenly it's in accordance with
my expectations. :)
 
G

Gunnar Hjalmarsson

Gunnar said:
I thought that \n means \015\012 on Windows. Now - after having re-read
your comments, re-read the "Newlines" section in "perldoc perlport", and
played around some more - I'm slowly realizing that it means \012 just
as on *nix, and that the \015\012 newline is only used on *saved* text
files.

Second thought. Please read this extract from "perldoc perlport":

"Perl uses \n to represent the "logical" newline, where what is logical
may depend on the platform in use. In MacPerl, \n always means \015. In
DOSish perls, \n usually means \012, but when accessing a file in "text"
mode, STDIO translates it to (or from) \015\012, depending on whether
you're reading or writing."

Doesn't it say that STDIO changes the meaning of \n on Windows? But that
is not correct, is it? Or am I still missing something?
 
T

Tim Greer

Gunnar said:
Second thought. Please read this extract from "perldoc perlport":

"Perl uses \n to represent the "logical" newline, where what is
logical may depend on the platform in use. In MacPerl, \n always means
\015. In DOSish perls, \n usually means \012, but when accessing a
file in "text" mode, STDIO translates it to (or from) \015\012,
depending on whether you're reading or writing."

Doesn't it say that STDIO changes the meaning of \n on Windows? But
that is not correct, is it? Or am I still missing something?

I thought it meant that it changes it so reading \015\012 would
translate it to \n, and writing it would change it from \n to \015\012.
It's been a _long time_ since I've used Windows. Maybe run a couple of
quick tests to verify and see exactly what it's doing (to avoid any
confusion), and then you'll know.
 
G

Gunnar Hjalmarsson

Tim said:
I thought it meant that it changes it so reading \015\012 would
translate it to \n, and writing it would change it from \n to \015\012.

That's apparently what's happening. I'm just questioning the possible
lack of clarity in that para.
It's been a _long time_ since I've used Windows. Maybe run a couple of
quick tests to verify and see exactly what it's doing (to avoid any
confusion), and then you'll know.

I did that already. :)
 
S

sln

I thought it meant that it changes it so reading \015\012 would
translate it to \n, and writing it would change it from \n to \015\012.
It's been a _long time_ since I've used Windows. Maybe run a couple of
quick tests to verify and see exactly what it's doing (to avoid any
confusion), and then you'll know.

Why don't you create a binary file in windows and insert 10 or 13 on a few
lines (but not both), then the pair in a few (reverse a few too), then
check the results.

Or, dial up Wally and ask him.

-sln
 
S

sln

Why don't you create a binary file in windows and insert 10 or 13 on a few
lines (but not both), then the pair in a few (reverse a few too), then
check the results.

Or, dial up Wally and ask him.

"Hey Wally, whats in that 'if()' statement?".
-sln
 
T

Tim Greer

Why don't you create a binary file in windows and insert 10 or 13 on a
few lines (but not both), then the pair in a few (reverse a few too),
then check the results.

Or, dial up Wally and ask him.

-sln

Who are you talking to? Who's using Windows? Who's creating a binary
file and needs to do that test? Were you replying to Gunnar?
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,995
Messages
2,570,230
Members
46,819
Latest member
masterdaster

Latest Threads

Top