Anonymous Monk has asked for the
wisdom of the Perl Monks concerning the following question:
Hi,
I have a file with these values,
Name
a
b
c
d
e
f
g
h
How can i save the first 3 values i.e. (a,b,c) to 3 different variables?
i.e.
$i = a
$j = b
$k = c
Need to repeat till the end of the file, so the next iteration these variable should have values,
$i = d
$j = e
$ = f
Re: Save first n values from a file
by LanX (Bishop) on Jan 10, 2014 at 10:40 UTC
|
file handles return single lines in scalar context
while ( my $a =<DATA> ){
my $b=<DATA>;
my $c=<DATA>;
print $a;
}
# while ( my $a =<DATA>, my $b=<DATA>, my $c=<DATA> ){
# print $a;
# }
__DATA__
a
b
c
d
e
f
g
h
please note the difference, the second version will stop after printing "d", since the last group has only 2 entries (i.e. $c is undef)
Cheers Rolf
( addicted to the Perl Programming Language)
| [reply] [d/l] [select] |
Re: Save first n values from a file
by Random_Walk (Prior) on Jan 10, 2014 at 10:33 UTC
|
Perhaps a hash, or an array is would suit your purpose better. Here is an example using an array, also showing a way to put the vals in $i, $j, $k and a way to use a hash.
Update: Added hash demo to code too, and better behaviour when it runs out of values
use strict;
use warnings;
my @names;
while (my $name = <DATA>) {
chomp $name; # remove newline
push @names, $name;
}
print "The third name is $names[2]\n";
my @copy = @names; # take a copy for the hash demo
my ($i, $j, $k);
while (@names) {
for (\$i, \$j, \$k) {
if (@names) {
$$_ = shift @names;
}
else {
$$_ = 'ran out of records'; # could use undef too
}
}
print "i: $i j:$j k: $k \n";
}
# and with a hash
my %hash;
while (@copy) {
%hash = (i=>'', j=>'', k=>''); # clear the hash
for my $key (qw(i j k)) {
$hash{$key} = shift @copy if @copy;
}
print "the hash contains $hash{$_} under $_\n" for ('i'..'k');
}
__DATA__
a
b
c
d
e
f
g
h
Cheers, R.
Pereant, qui ante nos nostra dixerunt!
| [reply] [d/l] [select] |
Re: Save first n values from a file
by johngg (Abbot) on Jan 10, 2014 at 12:09 UTC
|
This code builds an AoA by processing three lines at a time and pushing an anonymous array of chomped lines for each group.
$ perl -Mstrict -Mwarnings -MData::Dumper -e '
sub groupsOf (&$@);
open my $inFH, q{<}, \ <<EOD or die $!;
a
b
c
d
e
f
g
h
EOD
my @arr;
push @arr, groupsOf { chomp @_; [ @_ ] } 3, <$inFH>;
sub groupsOf (&$@)
{
my $rcToRun = shift;
my $groupsOf = shift;
my $rcDoIt;
$rcDoIt = sub
{
$rcToRun->(
map shift, 1 .. ( @_ < $groupsOf ? @_ : $groupsOf )
),
@_ ? &$rcDoIt : ();
};
&$rcDoIt;
}
print Data::Dumper->Dumpxs( [ \ @arr ], [ qw{ *arr } ] );'
@arr = (
[
'a',
'b',
'c'
],
[
'd',
'e',
'f'
],
[
'g',
'h'
]
);
$
I hope this is of interest.
Update: Simpler and assigns to three variables rather than constructing an AoA.
$ perl -Mstrict -Mwarnings -E '
> open my $inFH, q{<}, \ <<EOD or die $!;
> a
> b
> c
> d
> e
> f
> g
> h
> EOD
>
> while ( not eof $inFH )
> {
> my( $i, $j, $k ) =
> map { chomp; $_ }
> map { eof $inFH ? () : scalar <$inFH> }
> 1 .. 3;
> say
> q{$i - }, defined $i ? qq{$i; } : q{undef; },
> q{$j - }, defined $j ? qq{$j; } : q{undef; },
> q{$k - }, defined $k ? $k : q{undef};
> }'
$i - a; $j - b; $k - c
$i - d; $j - e; $k - f
$i - g; $j - h; $k - undef
$
| [reply] [d/l] [select] |
Re: Save first n values from a file
by Lennotoecom (Pilgrim) on Jan 10, 2014 at 12:16 UTC
|
this is the dark arts ^ ^,
but seriously, I think other monks won't approve, still:
for $x (f .. j){
chomp(${$x} = <DATA>);
}
print "$f $g $h $i $j\n";
__DATA__
a
b
c
d
e
update*
addressing the authors exact demands
here an addition:
do{for $x (i, g, k){
chomp(${$x} = <DATA>);
} print "$i $g $k\n";} until eof;
__DATA__
a
b
c
d
e
f
g
h
output:
a b c
d e f
g h
| [reply] [d/l] [select] |
|
| [reply] [d/l] |
|
yes, sorry
just couldn't restrain myself :)
I hope the readers will understand
| [reply] |
Re: Save first n values from a file
by kcott (Chancellor) on Jan 12, 2014 at 14:53 UTC
|
#!/usr/bin/env perl -l
use strict;
use warnings;
my @values;
while (<DATA>) {
chomp;
push @values, $_;
if (@values == 3) {
process_values(@values);
@values = ();
}
}
process_values(@values) if @values;
sub process_values {
my ($i, $j, $k) = @_;
print '$i = ', defined $i ? $i : '<undefined>';
print '$j = ', defined $j ? $j : '<undefined>';
print '$k = ', defined $k ? $k : '<undefined>';
}
__DATA__
a
b
c
d
e
f
g
h
Output:
$i = a
$j = b
$k = c
$i = d
$j = e
$k = f
$i = g
$j = h
$k = <undefined>
| [reply] [d/l] [select] |
Re: Save first n values from a file
by robby_dobby (Friar) on Jan 13, 2014 at 05:57 UTC
|
Others have offered varied solutions. Alternatively, you can use splice.
Once you have read all the names into an array, you can loop through that array to gather items 3 at a time:
while(@names) {
my ($i, $j, $k) = splice (@names, 0, 3);
printf('$i is %s, $j is %s, $k is %s', $i, $j, $k);
print "\n";
}
Note that if you have strict or warnings enabled, you will get errors like:
"Use of uninitialized value $k in printf". You can add error/null checking here to handle all of these. This would also mutate the @names array - keep a defensive copy around. :-) | [reply] [d/l] [select] |
Re: Save first n values from a file
by Anonymous Monk on Jan 10, 2014 at 20:57 UTC
|
Fastest way by far: - seek() to a position, relative to end-of-file, that you are quite sure is long enough to fit. ...
- Read a string starting from that position.
- Use a regex anchored at end-of-string to carve off the last three digits, e.g. /(\d+)\n(\d+)\n(\d+)$/ this assuming there are no whitespaces.
- The numbers you want are $1, $2, $3. (If they aren't, then die() because your assumption about "what you are quite sure is long enough" wasn't.)
You don't need to slog through an arbitrarily-long random access file just to find out what's at the end of it.
| [reply] |
Re: Save first n values from a file
by pvaldes (Chaplain) on Jan 12, 2014 at 15:19 UTC
|
use strict; use warnings;
my @foo = ();
while (<DATA>){ chomp;
if ($. < 4){push @foo, $_}}
print "my first variable is $foo[0]";
print "my second variable is $foo[1]";
print "my third variable is $foo[2]";
__DATA__
one
two
a beautiful tree, maybe an oak?
no need to read after "n lines"
And you can add also a fifth line to rename your variables and that's all:
my ($ball,$dog,$bird) = ($fo[1],$fo[2],$fo[0]); | [reply] [d/l] [select] |
Re: Save first n values from a file
by Anonymous Monk on Jan 10, 2014 at 20:58 UTC
|
Correction: "read a chunk of data regardless of 'string' boundaries." The actual bytes, please. | [reply] |
|
|