Re: How to dynamically taking the multiple input arguments?

2004-09-11 Thread John W. Krahn
Edward WIJAYA wrote:
Hi John,
Hello,
I tried your code.
But I still cannot remove the whitespace from each line.
Suppose I have two files.
fileA.txt:fileB.txt:
A B
A B
What I get is:
A B
A B
instead of
AB
AB
I tried to play around with this
section of your code but of no avail.
# clean up whitespace
for ( @data ) {
 s/^\s+//;
 s/\s+/ /g;
 s/ $/\n/;
 }
This should do what you want:
#!/usr/bin/perl
use warnings;
use strict;
my ( $line, @data );
while (  ) {
s/^\s+//;
s/\s+$//;
s/\s+/ /g;
$data[ $line++ ] .= $_ if /\S/;
$line = 0 if eof;
}
print map $_\n, @data;
__END__

John
--
use Perl;
program
fulfillment
--
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]
http://learn.perl.org/ http://learn.perl.org/first-response



How to dynamically taking the multiple input arguments?

2004-09-10 Thread Edward WIJAYA
Hi,
I have a simple code that take
currently fixed to take 3 input files and
append each line of these files together.
I wish to know is there anyway I can
write the code more flexibly so it can
dynamically take the input argument - from minimum
2 files to more.
Is there anywhere I can find information
about dealing with this matter? Any specific
module that cater this problem?
Thanks for your time beforehand.
Regards,
Edward WIJAYA
SINGAPORE
This is my current (terribly inefficient
and unflexible) code:
#!/usr/bin/perl -w
use strict;
use Data::Dumper;
if(scalar @ARGV ne 1)
{
print Usage: $0 file1 file2 [file3] etc\n;
exit(1);
}
#the above part doesn't seem to be working well/useful
my $file1 = $ARGV[0];
my @set1 = get_file_data($file1);
#Remove the whitspace and \n from each lines
@set1 = grep { s/^\s+//; s/\s+$//; s/\s+/ /g; length } @set1;
my $s1 = [EMAIL PROTECTED];
my $file2 = $ARGV[1];
my @set2 = get_file_data($file2);
@set2 = grep { s/^\s+//; s/\s+$//; s/\s+/ /g; length } @set2;
my $s2 = [EMAIL PROTECTED];
my $file3 = $ARGV[2];
my @set3 = get_file_data($file3);
@set3 = grep { s/^\s+//; s/\s+$//; s/\s+/ /g; length } @set3;
my $s3 = [EMAIL PROTECTED];

#Printout the appended lines from the data
print map { join(,$set1[$_],$set2[$_],$set3[$_]), \n } (0..$#set1);

#Subroutine
sub get_file_data {
my ($filename) = @_;
use strict;
use warnings;
# Initialize variables
my @filedata = ();
unless ( open( GET_FILE_DATA, $filename ) ) {
print STDERR Cannot open file \$filename\\n\n;
exit;
}
@filedata = GET_FILE_DATA;
close GET_FILE_DATA;
return (@filedata);
}
___END
--
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]
http://learn.perl.org/ http://learn.perl.org/first-response



Re: How to dynamically taking the multiple input arguments?

2004-09-10 Thread Errin Larsen
Well, I'm kinda new at this stuff myself, but Here's a couple of
things I see right away:


On Sat, 11 Sep 2004 10:27:44 +0800, Edward WIJAYA
[EMAIL PROTECTED] wrote:
 Hi,

SNIP

 #!/usr/bin/perl -w
  --You don't really need to use the -w flag here AND the 'use
warnings' in your subroutine
 down below.

 use strict;
-- Nice Job!!

 use Data::Dumper;
 
 if(scalar @ARGV ne 1)
 {
 print Usage: $0 file1 file2 [file3] etc\n;
 exit(1);
 }
 #the above part doesn't seem to be working well/useful
 

  --Try this:
  unless( @ARGV = 2 ) { die Usage: $0 file1 file2 [file3...]\n; }

 my $file1 = $ARGV[0];
--This is easier and prettier with this:
   my $file1 = shift;

 my @set1 = get_file_data($file1);
 
 #Remove the whitspace and \n from each lines
 @set1 = grep { s/^\s+//; s/\s+$//; s/\s+/ /g; length } @set1;
--You can get all the \n's out at once with a chomp:
chomp @set1;

  However, the whole get_file_data thing and chomping can all be
done like this:
open INFILE, $filename or die Couldn't open $filename: $!\n;
chomp( my @filedata = INFILE );

  Then, to clear out the whitespace from each line:
foreach( @filedata ) {
  s/\s+//g;
}

 my $s1 = [EMAIL PROTECTED];
 
 my $file2 = $ARGV[1];
 my @set2 = get_file_data($file2);
 @set2 = grep { s/^\s+//; s/\s+$//; s/\s+/ /g; length } @set2;
 my $s2 = [EMAIL PROTECTED];
 
 my $file3 = $ARGV[2];
 my @set3 = get_file_data($file3);
 @set3 = grep { s/^\s+//; s/\s+$//; s/\s+/ /g; length } @set3;
 my $s3 = [EMAIL PROTECTED];
 
 #Printout the appended lines from the data
 print map { join(,$set1[$_],$set2[$_],$set3[$_]), \n } (0..$#set1);
 
 #Subroutine
 sub get_file_data {
 
  my ($filename) = @_;
 
  use strict;
  use warnings;
 
  # Initialize variables
  my @filedata = ();
 
  unless ( open( GET_FILE_DATA, $filename ) ) {
  print STDERR Cannot open file \$filename\\n\n;
  exit;
  }
 
  @filedata = GET_FILE_DATA;
  close GET_FILE_DATA;
  return (@filedata);
 }
 

SNIP

Not much, I know, but I'm sure some of the others on the list will
help out more.  I'll work on this some more and post what I figure out
later.

--Errin

-- 
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]
http://learn.perl.org/ http://learn.perl.org/first-response




Re: How to dynamically taking the multiple input arguments?

2004-09-10 Thread Errin Larsen
Here ya go ... this works for me.  I tested it with up to 5 input
files and it was still workin'.  It does have a bug, though.  It
doesn't check whether all the input files are the same length.  Nor
did I test what happens when they AREN'T the same length.  Let me know
what ya think:

#!/usr/bin/perl

use warnings;
use strict;

unless( @ARGV = 2 ) { die Usage: $0 file1 file2 [file3...]\n; }

my @results;

foreach( @ARGV ) {
open IN, $_ or die Couldn't open $_: $!\n;
chomp( my @data = IN );
close IN;
foreach( @data ) { s/\s+//g; }
foreach( 0..$#data ) { $results[$_] .= $data[$_]; }
}   

foreach( @results ) { print $_\n; }

--Errin

-- 
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]
http://learn.perl.org/ http://learn.perl.org/first-response




Re: How to dynamically taking the multiple input arguments?

2004-09-10 Thread David Greenberg
foreach( @ARGV ) {
   open IN, $_ or die Couldn't open $_: $!\n;
   chomp( my @data = IN );
   close IN;
   foreach( @data ) { s/\s+//g; }
   foreach( 0..$#data ) { $results[$_] .= $data[$_]; }
}
This is a little shorter and saves on iterations:
for my $file (@ARGV) {
 open IN, $file or die Couldn't open $file: $!\n;
 @results = map { my $line = $_; chomp $line; $line =~ s/\s+//g;
$line } (IN);
 close IN;
}

-David

On Fri, 10 Sep 2004 11:35:09 -0500, Errin Larsen [EMAIL PROTECTED] wrote:
 Here ya go ... this works for me.  I tested it with up to 5 input
 files and it was still workin'.  It does have a bug, though.  It
 doesn't check whether all the input files are the same length.  Nor
 did I test what happens when they AREN'T the same length.  Let me know
 what ya think:
 
 #!/usr/bin/perl
 
 use warnings;
 use strict;
 
 unless( @ARGV = 2 ) { die Usage: $0 file1 file2 [file3...]\n; }
 
 my @results;
 
 foreach( @ARGV ) {
 open IN, $_ or die Couldn't open $_: $!\n;
 chomp( my @data = IN );
 close IN;
 foreach( @data ) { s/\s+//g; }
 foreach( 0..$#data ) { $results[$_] .= $data[$_]; }
 }
 
 foreach( @results ) { print $_\n; }
 
 
 
 --Errin
 
 --
 To unsubscribe, e-mail: [EMAIL PROTECTED]
 For additional commands, e-mail: [EMAIL PROTECTED]
 http://learn.perl.org/ http://learn.perl.org/first-response
 


-- 
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]
http://learn.perl.org/ http://learn.perl.org/first-response




Re: How to dynamically taking the multiple input arguments?

2004-09-10 Thread Errin Larsen
On Fri, 10 Sep 2004 12:44:51 -0400, David Greenberg
[EMAIL PROTECTED] wrote:
 foreach( @ARGV ) {
open IN, $_ or die Couldn't open $_: $!\n;
chomp( my @data = IN );
close IN;
foreach( @data ) { s/\s+//g; }
foreach( 0..$#data ) { $results[$_] .= $data[$_]; }
 }
 This is a little shorter and saves on iterations:
 for my $file (@ARGV) {
  open IN, $file or die Couldn't open $file: $!\n;
  @results = map { my $line = $_; chomp $line; $line =~ s/\s+//g;
 $line } (IN);
  close IN;
 }
 
 -David
 

Can you throw the 'chomp' in the assignment in that 'map' statement? 
Then, can you also throw in the substitution in the mix?  like this:
  @results = map{ my $line = chomp(  s/\s+//g ); } ( IN );

And if so, why not this:

  @results = map{ chomp( s/\s+//g ) } ( IN );

As long as we're playing Perl-Golf!!

I truly don't understand what 'map' is doing.  Can you explain it to
me?  I have tried to read perldoc -f map but it's a little weird and
hard to follow!

--Errin

-- 
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]
http://learn.perl.org/ http://learn.perl.org/first-response




Re: How to dynamically taking the multiple input arguments?

2004-09-10 Thread David Greenberg
I'm no expert, but chomp won't give you what you think it will:
my @arr = ('a', b\n, c\n);
print join (,,chomp (@arr));

This will print:
2

while this:
my @arr = ('a', b\n, c\n);
chomp (@arr);
print join (,,@arr);

will print:
a,b,c

Map will run whatever is in the code block (between the {}'s) on every
value in the list passed to it (between the ()'s).  The last statement
in the code block is like a return value.  Map builds the results list
out of all of the return values.  With a foreach loop, it would be:
my @results = ();
foreach (IN) {
 my $line = $_;
 chomp $line;
 $line =~ s/\s+//g;
 push (@results, $line); #appends $line to the @results list
}

Hope this helps.

-David

On Fri, 10 Sep 2004 11:58:30 -0500, Errin Larsen [EMAIL PROTECTED] wrote:
 On Fri, 10 Sep 2004 12:44:51 -0400, David Greenberg
 [EMAIL PROTECTED] wrote:
  foreach( @ARGV ) {
 open IN, $_ or die Couldn't open $_: $!\n;
 chomp( my @data = IN );
 close IN;
 foreach( @data ) { s/\s+//g; }
 foreach( 0..$#data ) { $results[$_] .= $data[$_]; }
  }
  This is a little shorter and saves on iterations:
  for my $file (@ARGV) {
   open IN, $file or die Couldn't open $file: $!\n;
   @results = map { my $line = $_; chomp $line; $line =~ s/\s+//g;
  $line } (IN);
   close IN;
  }
 
  -David
 
 
 Can you throw the 'chomp' in the assignment in that 'map' statement?
 Then, can you also throw in the substitution in the mix?  like this:
   @results = map{ my $line = chomp(  s/\s+//g ); } ( IN );
 
 And if so, why not this:
 
   @results = map{ chomp( s/\s+//g ) } ( IN );
 
 As long as we're playing Perl-Golf!!
 
 I truly don't understand what 'map' is doing.  Can you explain it to
 me?  I have tried to read perldoc -f map but it's a little weird and
 hard to follow!
 
 --Errin


-- 
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]
http://learn.perl.org/ http://learn.perl.org/first-response




Re: How to dynamically taking the multiple input arguments?

2004-09-10 Thread Bee



 foreach( @ARGV ) {
open IN, $_ or die Couldn't open $_: $!\n;
chomp( my @data = IN );
close IN;
foreach( @data ) { s/\s+//g; }
foreach( 0..$#data ) { $results[$_] .= $data[$_]; }
 }
 This is a little shorter and saves on iterations:
 for my $file (@ARGV) {
  open IN, $file or die Couldn't open $file: $!\n;
  @results = map { my $line = $_; chomp $line; $line =~ s/\s+//g;

@results seems would be re-assigned when the next file comes...

Besides, I guess chomp is not nesessary here.. \s+ means [\t\r\n\f]+, 
so \r, \n or \r\n would seem to be cleared by the s expression.


 $line } (IN);
  close IN;
 }
 

I would suggest to write in this way :
my @res = ();
foreach( @ARGV ) {
   open IN, $_ or die Couldn't open $_: $!\n;
   my @data = IN;
   close IN;

s/\s+//g  for @data;
@res = ( @res, @data );
}

Code not been tested, but the concept is something like this.
HTH



-- 
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]
http://learn.perl.org/ http://learn.perl.org/first-response




Re: How to dynamically taking the multiple input arguments?

2004-09-10 Thread Errin Larsen
On Fri, 10 Sep 2004 13:17:40 -0400, David Greenberg
[EMAIL PROTECTED] wrote:
 I'm no expert, but chomp won't give you what you think it will:
 my @arr = ('a', b\n, c\n);
 print join (,,chomp (@arr));
 
 This will print:
 2
 
 while this:
 my @arr = ('a', b\n, c\n);
 chomp (@arr);
 print join (,,@arr);
 
 will print:
 a,b,c
 
 Map will run whatever is in the code block (between the {}'s) on every
 value in the list passed to it (between the ()'s).  The last statement
 in the code block is like a return value.  Map builds the results list
 out of all of the return values.  With a foreach loop, it would be:
 my @results = ();
 foreach (IN) {
  my $line = $_;
  chomp $line;
  $line =~ s/\s+//g;
  push (@results, $line); #appends $line to the @results list
 }
 
 Hope this helps.
 
 -David
 
 

Thanks, David, for the 'map' explanation.  However, I've been playing
with this code, and, after your suggestion (above) it seems to be
broken.  Originally, the question was, taking atleast 2 seperate text
files on the command line, smoosh them together like this:

# ./smoosher file1 file2
OneFirst
TwoSecond
ThreeThird

if our text files are:
file1:
One
Two
Three

file2:
First
Second
Third

The code I have so far is (after your suggestion):

smoosher:
#!/usr/bin/perl

use warnings;
use strict;

unless( @ARGV = 2 ) { die Usage: $0 file1 file2 [file3...]\n; }

my @results = ();

foreach my $file ( @ARGV ) {
open IN, $file or die Couldn't open $file: $!\n;
@results = map { my $line = $_; chomp $line; $line =~
s/\s+//g; $line } (IN);
close IN;
}   

foreach( @results ) { print $_\n; }

The first 'foreach' block in my original code, which was working, was:

foreach my $file ( @ARGV ) {
   open IN, $file or die Couldn't open $file: $!\n;
   chomp( my @data = IN );
   close IN;
   foreach( @data ) { s/\s+//g; }
   foreach( 0..$#data ) { $results[$_] .= $data[$_]; }
}

So my question is, how can we use the map function, as you suggest, to
reduce the number of iterations, yet still keep our desired output? 
The key was the
  $results[$_] .= $data[$_];
line in there, which appended the current files line to the results
array, as opposed to replacing it, which is what our new code seems to
do.

--Errin

-- 
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]
http://learn.perl.org/ http://learn.perl.org/first-response




Re: How to dynamically taking the multiple input arguments?

2004-09-10 Thread Errin Larsen
On Sat, 11 Sep 2004 02:20:32 +0800, Bee [EMAIL PROTECTED] wrote:
 
 
  foreach( @ARGV ) {
 open IN, $_ or die Couldn't open $_: $!\n;
 chomp( my @data = IN );
 close IN;
 foreach( @data ) { s/\s+//g; }
 foreach( 0..$#data ) { $results[$_] .= $data[$_]; }
  }
  This is a little shorter and saves on iterations:
  for my $file (@ARGV) {
   open IN, $file or die Couldn't open $file: $!\n;
   @results = map { my $line = $_; chomp $line; $line =~ s/\s+//g;
 
 @results seems would be re-assigned when the next file comes...
 
 Besides, I guess chomp is not nesessary here.. \s+ means [\t\r\n\f]+,
 so \r, \n or \r\n would seem to be cleared by the s expression.
 
  $line } (IN);
   close IN;
  }
 
 
 I would suggest to write in this way :
 my @res = ();
 foreach( @ARGV ) {
open IN, $_ or die Couldn't open $_: $!\n;
my @data = IN;
close IN;
 
 s/\s+//g  for @data;
 @res = ( @res, @data );
 }
 
 Code not been tested, but the concept is something like this.
 HTH
 
 

Ok ... Thanks for helpin' out, HTH!  I tried out your suggestions and
now the code looks like this:

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

unless( @ARGV = 2 ) { die Usage: $0 file1 file2 [file3...]\n; }

my @results = ();
foreach my $file ( @ARGV ) {
open IN, $file or die Couldn't open $file: $!\n;
my @data = IN;
close IN;
s/\s+//g  foreach( @data );
@results = ( @results, @data );
}   

foreach( @results ) { print $_\n; }

But now the output is as follows.  We want the output to look like this:
  OneFirst
  TwoSecond
  ThreeThird
But instead, it's coming out like this:
   One
   Two
   Three
   First
   Second
   Third
Given the two test input files:
file1:   file2:
OneFirst
TwoSecond
Three  Third

--Errin

-- 
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]
http://learn.perl.org/ http://learn.perl.org/first-response




Re: How to dynamically taking the multiple input arguments?

2004-09-10 Thread David Greenberg
Opps, I missed that.  Instead of:
@results = map { my $line = $_; chomp $line; $line =~ s/\s+//g; $line } (@data);
try:
my @newresults = map { my $line = $_; chomp $line; $line =~ s/\s+//g;
shift (@results) . $line } (@data);
@results = @newresults;

-David

On Fri, 10 Sep 2004 13:40:04 -0500, Errin Larsen [EMAIL PROTECTED] wrote:
 On Sat, 11 Sep 2004 02:20:32 +0800, Bee [EMAIL PROTECTED] wrote:
 
 
   foreach( @ARGV ) {
  open IN, $_ or die Couldn't open $_: $!\n;
  chomp( my @data = IN );
  close IN;
  foreach( @data ) { s/\s+//g; }
  foreach( 0..$#data ) { $results[$_] .= $data[$_]; }
   }
   This is a little shorter and saves on iterations:
   for my $file (@ARGV) {
open IN, $file or die Couldn't open $file: $!\n;
@results = map { my $line = $_; chomp $line; $line =~ s/\s+//g;
 
  @results seems would be re-assigned when the next file comes...
 
  Besides, I guess chomp is not nesessary here.. \s+ means [\t\r\n\f]+,
  so \r, \n or \r\n would seem to be cleared by the s expression.
 
   $line } (IN);
close IN;
   }
  
 
  I would suggest to write in this way :
  my @res = ();
  foreach( @ARGV ) {
 open IN, $_ or die Couldn't open $_: $!\n;
 my @data = IN;
 close IN;
 
  s/\s+//g  for @data;
  @res = ( @res, @data );
  }
 
  Code not been tested, but the concept is something like this.
  HTH
 
 
 
 Ok ... Thanks for helpin' out, HTH!  I tried out your suggestions and
 now the code looks like this:
 
 #!/usr/bin/perl
 use warnings;
 use strict;
 
 unless( @ARGV = 2 ) { die Usage: $0 file1 file2 [file3...]\n; }
 
 my @results = ();
 foreach my $file ( @ARGV ) {
 open IN, $file or die Couldn't open $file: $!\n;
 my @data = IN;
 close IN;
 s/\s+//g  foreach( @data );
 @results = ( @results, @data );
 }
 
 foreach( @results ) { print $_\n; }
 
 But now the output is as follows.  We want the output to look like this:
   OneFirst
   TwoSecond
   ThreeThird
 But instead, it's coming out like this:
One
Two
Three
First
Second
Third
 Given the two test input files:
 file1:   file2:
 OneFirst
 TwoSecond
 Three  Third
 
 --Errin


-- 
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]
http://learn.perl.org/ http://learn.perl.org/first-response




Re: How to dynamically taking the multiple input arguments?

2004-09-10 Thread Errin Larsen
On Fri, 10 Sep 2004 15:01:34 -0400, David Greenberg
[EMAIL PROTECTED] wrote:
 Opps, I missed that.  Instead of:
 @results = map { my $line = $_; chomp $line; $line =~ s/\s+//g; $line } (@data);
 try:
 my @newresults = map { my $line = $_; chomp $line; $line =~ s/\s+//g;
 shift (@results) . $line } (@data);
 @results = @newresults;
 
 -David
 

Ok ... please forgive my n00b-ness, but can you help me understand a
couple of things here.  This part:

   shift (@results) . $line

Is it the same as:

   shift @results . $line

I'm thinking no.  But I don't know what the difference is.  I also
don't understand what exactly that shift is doing, but if I understand
the difference with the parens maybe It'll start to make more sense to
me.

--Errin

-- 
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]
http://learn.perl.org/ http://learn.perl.org/first-response




Re: How to dynamically taking the multiple input arguments?

2004-09-10 Thread Bee
 Ok ... Thanks for helpin' out, HTH!  I tried out your suggestions and
 now the code looks like this:

You are welcome, but my name is Bee, HTH stands for 'Hope This Help'


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

 unless( @ARGV = 2 ) { die Usage: $0 file1 file2 [file3...]\n; }

 my @results = ();
 foreach my $file ( @ARGV ) {
 open IN, $file or die Couldn't open $file: $!\n;
 my @data = IN;
 close IN;
 s/\s+//g  foreach( @data );
 @results = ( @results, @data );

Oops... sorry for I've confused for what you expected, so instead the above
line with this :
$results[$_] .= $data[$_] for (0..$#data) ; # would almostly do what you
want now !







-- 
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]
http://learn.perl.org/ http://learn.perl.org/first-response




Re: How to dynamically taking the multiple input arguments?

2004-09-10 Thread David Greenberg
I'm not sure if shift (@results) . $line; and shift @results . $line
would work differently.  It depends on whether the order of operations
gives precedence to . or to handing an argument to a function.  My
guess is that . gets precedence, in which case shift @results . $line;
will give you something weird that you don't want.

I suggest you look up the perldocs on shift, but basically if you have
any array, like:
my @arr = ('a', 'b', 'c');

the result of:
print shift (@arr);

will be:
a

and @arr will now only be:
('b', 'c')

In other words, it takes the first element off of the array.  It is
often used to get arguments to a function:
sub foo {
 my $arg1 = shift;
 my $arg2 = shift;
 print $arg1 .   . $arg2;
}
foo (hello, world);

would print:
hello world

So, shift (@results) . $line; is taking the next value from @results
and appending $line to it.
That value will then be the next value in @newresults.

It takes a bit of getting used to.  I suggest reading a little about
functional programming to fully grasp the list manipulation functions
like map, grep, split, join, etc.

-David


On Fri, 10 Sep 2004 14:37:28 -0500, Errin Larsen [EMAIL PROTECTED] wrote:
 On Fri, 10 Sep 2004 15:01:34 -0400, David Greenberg
 [EMAIL PROTECTED] wrote:
  Opps, I missed that.  Instead of:
  @results = map { my $line = $_; chomp $line; $line =~ s/\s+//g; $line } (@data);
  try:
  my @newresults = map { my $line = $_; chomp $line; $line =~ s/\s+//g;
  shift (@results) . $line } (@data);
  @results = @newresults;
 
  -David
 
 
 Ok ... please forgive my n00b-ness, but can you help me understand a
 couple of things here.  This part:
 
shift (@results) . $line
 
 Is it the same as:
 
shift @results . $line
 
 I'm thinking no.  But I don't know what the difference is.  I also
 don't understand what exactly that shift is doing, but if I understand
 the difference with the parens maybe It'll start to make more sense to
 me.
 
 --Errin


-- 
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]
http://learn.perl.org/ http://learn.perl.org/first-response




Re: How to dynamically taking the multiple input arguments?

2004-09-10 Thread Bee
  Opps, I missed that.  Instead of:
  @results = map { my $line = $_; chomp $line; $line =~ s/\s+//g; $line }
(@data);
  try:
  my @newresults = map { my $line = $_; chomp $line; $line =~ s/\s+//g;
  shift (@results) . $line } (@data);
  @results = @newresults;
 
  -David

This works fine, but can be simplier :
my @newresults = map { s/\s+//g;  shift (@results) . $_ } (@data);


 Ok ... please forgive my n00b-ness, but can you help me understand a
 couple of things here.  This part:

shift (@results) . $line

This means :
$x = shift @result; # where $x means to $_ or the value carries in memory.
$x = $x . $line


 Is it the same as:

shift @results . $line

While this means :

$x = @results . $line ; # @results here means scalar @results ( how many
elems inside @results )
shift $x ; # then cause error.


 I'm thinking no.  But I don't know what the difference is.  I also

The difference is the scope for the 'shift' , with ( ), the scope for shift
is @results,
without ( ) , the scope for shift is @results . $line .

 don't understand what exactly that shift is doing, but if I understand

perldoc -f shift



-- 
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]
http://learn.perl.org/ http://learn.perl.org/first-response




Fwd: How to dynamically taking the multiple input arguments?

2004-09-10 Thread Errin Larsen
I forgot to CC the list with my last post!  sorry, won't happen again.
--Errin


-- Forwarded message --
From: Errin Larsen [EMAIL PROTECTED]
Date: Fri, 10 Sep 2004 15:46:33 -0500
Subject: Re: How to dynamically taking the multiple input arguments?
To: Bee [EMAIL PROTECTED]

Alrighty ... So the code I've got now is below.  Some of the
variables' names have changed to make things slightly less confusing
(probably only less confusing for me!).  I also moved those parens
arount the 'shift' function so it communicates the precendence (again,
in my opinion) a little more clearly.  I have tested this and it seems
to work! comments?

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

unless( @ARGV = 2 ) { die Usage: $0 file1 file2 [file3...]\n; }

my @final_results = ();
foreach my $file ( @ARGV ) {
open IN, $file or die Couldn't open $file: $!\n;
my @tmp_results = map{ s/\s+//g; ( shift @final_results ).$_ } ( IN );
@final_results = @tmp_results;
close IN;
}

print $_\n foreach( @final_results );

btw, thanks for all the help and explanations David and Bee (sorry
about my ignorance of the HTH!).  I hope Edward (the original poster!)
has been paying attention!

--Errin

-- 
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]
http://learn.perl.org/ http://learn.perl.org/first-response




Re: How to dynamically taking the multiple input arguments?

2004-09-10 Thread John W. Krahn
Edward WIJAYA wrote:
Hi,
Hello,
I have a simple code that take
currently fixed to take 3 input files and
append each line of these files together.
I wish to know is there anyway I can
write the code more flexibly so it can
dynamically take the input argument - from minimum
2 files to more.
Is there anywhere I can find information
about dealing with this matter? Any specific
module that cater this problem?
You could use the paste program to do that.
man paste

This is my current (terribly inefficient
and unflexible) code:
#!/usr/bin/perl -w
use strict;
use Data::Dumper;
if(scalar @ARGV ne 1)
You are using 'ne' which compares strings when you should be using '!=' which 
is used to compare numbers.  Both the comparison operator and the if 
conditional force scalar context so using 'scalar' is redundant.

if ( @ARGV != 1 )
However that only works if the command line has exactly one filename and you 
want to require two or more.

if ( @ARGV = 2 )

{
print Usage: $0 file1 file2 [file3] etc\n;
exit(1);
}
#the above part doesn't seem to be working well/useful
my $file1 = $ARGV[0];
my @set1 = get_file_data($file1);
   
perldoc -q quoting
Found in /usr/lib/perl5/5.8.2/pod/perlfaq4.pod
   What's wrong with always quoting $vars?

#Remove the whitspace and \n from each lines
@set1 = grep { s/^\s+//; s/\s+$//; s/\s+/ /g; length } @set1;
my $s1 = [EMAIL PROTECTED];
my $file2 = $ARGV[1];
my @set2 = get_file_data($file2);
@set2 = grep { s/^\s+//; s/\s+$//; s/\s+/ /g; length } @set2;
my $s2 = [EMAIL PROTECTED];
my $file3 = $ARGV[2];
my @set3 = get_file_data($file3);
@set3 = grep { s/^\s+//; s/\s+$//; s/\s+/ /g; length } @set3;
my $s3 = [EMAIL PROTECTED];

#Printout the appended lines from the data
print map { join(,$set1[$_],$set2[$_],$set3[$_]), \n } (0..$#set1);

#Subroutine
sub get_file_data {
my ($filename) = @_;
use strict;
use warnings;
use() keeps track of which modules have been loaded so use()ing the same 
module more than once will not incur more overhead and will not do anything 
useful either.


# Initialize variables
my @filedata = ();
my() creates a lexical variable in an undefined state so assigning an 
undefined value to it is redundant.


unless ( open( GET_FILE_DATA, $filename ) ) {
print STDERR Cannot open file \$filename\\n\n;
You should include the $! (or $^E) variable in the error message so you know 
why open() failed.


exit;
}
@filedata = GET_FILE_DATA;
close GET_FILE_DATA;
return (@filedata);
If you had used a lexical filehandle you could have skipped the assignment to 
an array.


}
___END
A valid __END__ token has two underscore characters before and after 'END'.
You have two basic options for merging files, store all the contents in memory 
which may run out of memory, or read each file line by line which may run out 
of file handles.

If the aggregate data will fit in memory you can do this:
#!/usr/bin/perl
use warnings;
use strict;
my ( $line, @data );
while (  ) {
$data[ $line++ ] .= $_ if /\S/;
$line = 0 if eof;
}
# clean up whitespace
for ( @data ) {
s/^\s+//;
s/\s+/ /g;
s/ $/\n/;
}
print @data;
__END__
And if you need to read each file a line at a time you could do something like 
this:

#!/usr/bin/perl
use warnings;
use strict;
my @fhs = map { open my $fh, '', $_ or die $_: $!; $fh } @ARGV;
while ( @fhs ) {
my $line = '';
for ( @fhs ) {
defined( my $curr = $_ ) or next;
redo unless $curr =~ /\S/;
$line .= $curr;
}
for ( $line ) {
s/^\s+//;
s/\s+/ /g;
s/ $/\n/;
}
print $line;
@fhs = grep !eof( $_ ), @fhs;
}
__END__

John
--
use Perl;
program
fulfillment
--
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]
http://learn.perl.org/ http://learn.perl.org/first-response



Re: How to dynamically taking the multiple input arguments?

2004-09-10 Thread John W. Krahn
Errin Larsen wrote:
On Fri, 10 Sep 2004 12:44:51 -0400, David Greenberg
[EMAIL PROTECTED] wrote:
foreach( @ARGV ) {
 open IN, $_ or die Couldn't open $_: $!\n;
 chomp( my @data = IN );
 close IN;
 foreach( @data ) { s/\s+//g; }
 foreach( 0..$#data ) { $results[$_] .= $data[$_]; }
}
This is a little shorter and saves on iterations:
for my $file (@ARGV) {
open IN, $file or die Couldn't open $file: $!\n;
@results = map { my $line = $_; chomp $line; $line =~ s/\s+//g;
$line } (IN);
close IN;
}
Can you throw the 'chomp' in the assignment in that 'map' statement? 
No.
Then, can you also throw in the substitution in the mix?
No.
  like this:
  @results = map{ my $line = chomp(  s/\s+//g ); } ( IN );
The substitution operator returns the number of substitutions performed or 
false if there were no substitutions.  chomp() returns the number of chomps 
performed.  map returns the value of the last statement in the code block.

So, assuming s/\s+//g returns a number and $/ hasn't been changed, chomp will 
assign 0 to $line which map will return for every line from IN.


And if so, why not this:
  @results = map{ chomp( s/\s+//g ) } ( IN );
Again, map will return 0 for every line from IN.
Also, the parentheses around the readline operator are redundant as map forces 
list context.


As long as we're playing Perl-Golf!!
I truly don't understand what 'map' is doing.  Can you explain it to
me?  I have tried to read perldoc -f map but it's a little weird and
hard to follow!
map takes a list, modifies each element, and returns the modified list.

John
--
use Perl;
program
fulfillment
--
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]
http://learn.perl.org/ http://learn.perl.org/first-response



Re: How to dynamically taking the multiple input arguments?

2004-09-10 Thread John W. Krahn
Bee wrote:
I would suggest to write in this way :
my @res = ();
foreach( @ARGV ) {
   open IN, $_ or die Couldn't open $_: $!\n;
   my @data = IN;
   close IN;
s/\s+//g  for @data;
@res = ( @res, @data );
You are copying the @res array.  It would be more efficient using push.
push @res, @data;
John
--
use Perl;
program
fulfillment
--
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]
http://learn.perl.org/ http://learn.perl.org/first-response



Re: How to dynamically taking the multiple input arguments?

2004-09-10 Thread John W. Krahn
Errin Larsen wrote:
Ok ... please forgive my n00b-ness, but can you help me understand a
couple of things here.  This part:
   shift (@results) . $line
Is it the same as:
   shift @results . $line
I'm thinking no.  But I don't know what the difference is.  I also
don't understand what exactly that shift is doing, but if I understand
the difference with the parens maybe It'll start to make more sense to
me.
If you had actually tried to run them you would have seen that the second one 
does not even compile.  :-)

John
--
use Perl;
program
fulfillment
--
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]
http://learn.perl.org/ http://learn.perl.org/first-response



Re: How to dynamically taking the multiple input arguments?

2004-09-10 Thread Edward WIJAYA
Hi John,
I tried your code.
But I still cannot remove the whitespace from each line.
Suppose I have two files.
fileA.txt:fileB.txt:
A B
A B
What I get is:
A B
A B
instead of
AB
AB
I tried to play around with this
section of your code but of no avail.
# clean up whitespace
for ( @data ) {
 s/^\s+//;
 s/\s+/ /g;
 s/ $/\n/;
 }
Hope to heare from you again.
Regards
Edward WIJAYA
--
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]
http://learn.perl.org/ http://learn.perl.org/first-response