On Wed, Apr 21, 2010 at 4:21 AM, Dan Track <dan.tr...@gmail.com> wrote:

> 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.<http://fedoraproject.org/wiki/Mailing_list_guidelines>
>

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@lists.fedoraproject.org
To unsubscribe or change subscription options:
https://admin.fedoraproject.org/mailman/listinfo/users
Guidelines: http://fedoraproject.org/wiki/Mailing_list_guidelines

Reply via email to