On Wed, Apr 21, 2010 at 4:21 AM, Dan Track <dan.track@xxxxxxxxx> wrote:
Hey
Can you please mark as OT in the subject next time? That way anyone not interested in non-Fedora specific questions can easily filter off topic subjects out.
sure, I'll provide some tips.
-w is deprecated. use warnings; instead
very good. always use strict;
this is a common error for ex-C/Java programmers, however in Perl there's no need to predefine variables. In fact, variables should be defined only in their smallest possible scope. This happens naturally if you define them as you use them.
this is an ok name for learning, but in real scripts use a name that describes the contents, rather than the structure.
new method is 3-argument open, with lexically scoped filehandle:
open( my $passwd, '<', $file ) or die "Can't open '$file': $!";
this reads from the filehandle until eof, putting the results in $_. It is convenient to use $_, but it is usually advisable to create a new lexically scoped variable.
while( my $line = <$passwd> ) {
if these hadn't been pre-defined, this line would read as follows and would keep $login, $p, etc scoped to this while block
my ($login,$p,$uid,$gid,$gecos,$dir,$s) = split ':', $line;
This structure works well if you wanted to look up the characteristics of a given $login as hash access is great for lookups. but if you wanted to just reorder all of them, maybe an array of hashes would be better? just a thought.
as others have mentioned, to perform numeric comparisons use the "spaceship" operator: <=>
now, note how many hash accesses your loop performs. each time the sort wishes to compare two values, it must perform two nested hash lookups. As your Perl improves, you will learn how to make this sort more efficient - one common method is called the Schwartzian Transform. (No relation to Spaceballs)
Hope my comments helped. Welcome to Perl.
Hi,
Hey
I appreciate that this is off-topic and wholly understand if I don't
get an answer, although one would really appreciate it if I do get an
answer :)
Can you please mark as OT in the subject next time? That way anyone not interested in non-Fedora specific questions can easily filter off topic subjects out.
Basically to improve my perl scripting, I've given myself a challenge
where I would like to order the users in the passwd file by uid, I
could do this in another language but I'm focused on improving my perl
scripting. The script I've written so far is below, I've managed to
figure out hashes and have read in the file and created a hash of
hashes. It's after this that I'm stuck, I'm struggling to order the
hash of hashes by uid and then print the ordered list out? Can someone
please help me to finish this off? I'm trying to avoid using perl
modules as I want to improve my scripting ability.
sure, I'll provide some tips.
#!/usr/bin/perl -w
-w is deprecated. use warnings; instead
use strict;
very good. always use strict;
my ( $login, $p, $uid, $gid, $gecos, $dir, $s );
my $k;
my $v;
my $key;
my $ip;
my $value;
my @sorted=();
my @uid=();
this is a common error for ex-C/Java programmers, however in Perl there's no need to predefine variables. In fact, variables should be defined only in their smallest possible scope. This happens naturally if you define them as you use them.
my %HoH = ();
this is an ok name for learning, but in real scripts use a name that describes the contents, rather than the structure.
my $file='/etc/passwd';
open( PASSWD, "< $file" ) or die "Can't open $file : $!";
new method is 3-argument open, with lexically scoped filehandle:
open( my $passwd, '<', $file ) or die "Can't open '$file': $!";
while( <PASSWD> ) {
this reads from the filehandle until eof, putting the results in $_. It is convenient to use $_, but it is usually advisable to create a new lexically scoped variable.
while( my $line = <$passwd> ) {
( $login, $p, $uid, $gid, $gecos, $dir, $s ) = split( ':' );
if these hadn't been pre-defined, this line would read as follows and would keep $login, $p, etc scoped to this while block
my ($login,$p,$uid,$gid,$gecos,$dir,$s) = split ':', $line;
$HoH{ $login }{ 'login' } = $login;
$HoH{ $login }{ 'p' } = $p;
$HoH{ $login }{ 'uid' } = $uid;
$HoH{ $login }{ 'gid' } = $gid;
$HoH{ $login }{ 'gecos' } = $gecos;
$HoH{ $login }{ 'dir' } = $dir;
$HoH{ $login }{ 's' } = $s;
#print "$login\n";
}
This structure works well if you wanted to look up the characteristics of a given $login as hash access is great for lookups. but if you wanted to just reorder all of them, maybe an array of hashes would be better? just a thought.
close PASSWD;
#while (($k,$v) = each %HoH) {
# print "While Loop: $k\n";
#}
#foreach $ip (keys %HoH) {
# print "First For: $ip\n";
# while (($key, $value) = each %{ $HoH{$ip} } ) {
# print "$key = $value \n";
# }
# print "\n";
#}
#while ( ($k, $v) = each %HoH ) {
# print "$k: \n";
# while ( ($key, $value) = each %$v ) {
# print "$key=$value ";
# }
# print "\n";
#}
#for $k ( sort keys %HoH ) {
# print "$k: ";
# for $v ( sort keys %{ $HoH{$k} } ) {
# print "$v=$HoH{$k}{$v} ";
# }
# print "\n";
#}
#@sorted = sort { $HoH{$a} cmp $HoH{$b} } keys %HoH;
#print "@sorted\n";
#foreach my $sorted ( sort { $HoH{$a}->{"uid"} cmp $HoH{$b}->{"uid"} }
keys %HoH)
foreach my $sorted ( sort { $HoH->{$a}{uid} cmp $HoH->{$b}{uid} } keys %HoH)
{
print STDOUT "$HoH{$sorted}\n"
}
as others have mentioned, to perform numeric comparisons use the "spaceship" operator: <=>
now, note how many hash accesses your loop performs. each time the sort wishes to compare two values, it must perform two nested hash lookups. As your Perl improves, you will learn how to make this sort more efficient - one common method is called the Schwartzian Transform. (No relation to Spaceballs)
Thank in advance for any help.
Hope my comments helped. Welcome to Perl.
--
-jp
Some folks say it was a miracle. St. Francis suddenly appeared and knocked the next pitch clean over the fence. Other folks say it was just a lucky swing.
deepthoughtsbyjackhandey.com
-- users mailing list users@xxxxxxxxxxxxxxxxxxxxxxx To unsubscribe or change subscription options: https://admin.fedoraproject.org/mailman/listinfo/users Guidelines: http://fedoraproject.org/wiki/Mailing_list_guidelines