Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Misbehaving sort function

7 views
Skip to first unread message

Vahid Moghaddasi

unread,
Nov 8, 2005, 11:35:23 AM11/8/05
to
Hi,
I have been trying to sort -u the password file /etc/passwd by its
first field (username) but for some reason sort is giving me a wrong
result. This is what I used:
"sort -t : -k 1,1 /etc/passwd" I do not use -u to see the result of the

sort command.
In the passwd file, I have the first 5 lines copied to the buttom of
the file (duplicate system accounts, root,daemon,bin,sys,adm with
different uid,gid's ) I have the users in the middle.
When I sort -u, I would like to see either the top 5 system users or
the bottom ones but I see one from top, one from the bottom and so on.
There is no pattern to the output, it seems that -k 1,1 does not have
any effect at all.
I would appreciate if someone shed a light on this or paste a function
to do the sort for me.
I need to sort by username and in another function by UID.
Thanks,
Vahid.

Paul Lalli

unread,
Nov 8, 2005, 11:42:37 AM11/8/05
to

It sounds an awful lot like you're confusing the Unix command 'sort'
with the Perl function 'sort'. While they have the same name, they
have nothing else in common.

If you're looking for a Perl solution to your problem, you should start
by making an attempt at a Perl solution, and then posting your attempt
here if it doesn't work.

Paul Lalli

Vahid Moghaddasi

unread,
Nov 8, 2005, 12:08:49 PM11/8/05
to

Paul Lalli wrote:
> It sounds an awful lot like you're confusing the Unix command 'sort'
> with the Perl function 'sort'. While they have the same name, they
> have nothing else in common.
>
> If you're looking for a Perl solution to your problem, you should start
> by making an attempt at a Perl solution, and then posting your attempt
> here if it doesn't work.
>
I am looking for a perl solution which gives me a similar result as
sort -t: -k1,1 in unix.
Unix sort command does not guarantee order of the sort as I mentioned
in my posting.

xho...@gmail.com

unread,
Nov 8, 2005, 12:33:49 PM11/8/05
to
"Vahid Moghaddasi" <mogha...@gmail.com> wrote:
> Paul Lalli wrote:
> > It sounds an awful lot like you're confusing the Unix command 'sort'
> > with the Perl function 'sort'. While they have the same name, they
> > have nothing else in common.
> >
> > If you're looking for a Perl solution to your problem, you should start
> > by making an attempt at a Perl solution, and then posting your attempt
> > here if it doesn't work.
> >
> I am looking for a perl solution which gives me a similar result as
> sort -t: -k1,1 in unix.

It seems like you are looking for a Perl solution that does what you think
"sort -t: -k1,1" should do, rather than what it actually does do. But
your description of what you think it should do is not clear, so how
can we help you?

> Unix sort command does not guarantee order of the sort as I mentioned
> in my posting.

The sort command doesn't sort? Wow! But that wasn't what I got out of
your first post. It sounded like it sorted properly, but that the behavior
of the -u switch was the thing that didn't do what you wanted. Now it is
the sort itself?

Maybe you are looking for this:

awk -F: '{print $1}' | sort -u


Xho

--
-------------------- http://NewsReader.Com/ --------------------
Usenet Newsgroup Service $9.95/Month 30GB

Paul Lalli

unread,
Nov 8, 2005, 1:02:42 PM11/8/05
to

Okay. So my advice remains the same. What have you tried so far (in
Perl)? How did it go wrong? What part do you need help with?

A few helpful pointers might be:
perldoc -f open
perldoc -f readline
perldoc -f sort
perldoc -f print

Paul Lalli

Vahid Moghaddasi

unread,
Nov 8, 2005, 1:41:03 PM11/8/05
to
Paul Lalli wrote:
>
> Okay. So my advice remains the same. What have you tried so far (in
> Perl)? How did it go wrong? What part do you need help with?
>
> A few helpful pointers might be:
> perldoc -f open
> perldoc -f readline
> perldoc -f sort
> perldoc -f print
>
Paul,
Here is what I did in perl but it is a system call so it not really a
perl sort function, I would like to change this to a native perl sort
if possible.
system(" cat passwd | awk -F: '{printf "%s-%04d %s:%s:%s:%s:%s:%s:% \
s\n",$1,NR,$1,$2,$3,$4,$5,$6,$7}' | sort -k1,1 | sed -e 's/-/ /' | \
sort -k1,1 -u | sort -k2,2 | cut -d " " -f3-");

I need to remove the duplicate username from the password file if they
appear again while parsing the file. For example if root is at the top
of the file, any second username 'root' should be discarded.
Thanks,

Paul Lalli

unread,
Nov 8, 2005, 1:51:26 PM11/8/05
to

I'm seriously starting to feel like I'm talking to a brick wall.
You're right, that's *not* a Perl solution. No one here is likely to
write a Perl solution for you. What we *will* do is HELP you with your
own Perl solution. So go make an attempt at solving your problem with
Perl, then come back here if that solution doesn't work, and we can
help you figure out why.

This is the third and final time I give you this advice. Go make an
attempt. Then ask us for help with the results of that attempt if
needed.

Paul Lalli

A. Sinan Unur

unread,
Nov 8, 2005, 4:15:34 PM11/8/05
to
"Paul Lalli" <mri...@gmail.com> wrote in
news:1131475886.6...@f14g2000cwb.googlegroups.com:

> Vahid Moghaddasi wrote:
>> Paul Lalli wrote:
>> >
>> > Okay. So my advice remains the same. What have you tried so far
>> > (in Perl)?

...

>> system(" cat passwd | awk -F: '{printf "%s-%04d %s:%s:%s:%s:%s:%s:% \
>> s\n",$1,NR,$1,$2,$3,$4,$5,$6,$7}' | sort -k1,1 | sed -e 's/-/ /' | \
>> sort -k1,1 -u | sort -k2,2 | cut -d " " -f3-");

...

> I'm seriously starting to feel like I'm talking to a brick wall.

It would be funny if it weren't so tragic.

Sinan

Jim Gibson

unread,
Nov 8, 2005, 5:56:30 PM11/8/05
to
In article <1131467723.4...@g47g2000cwa.googlegroups.com>,
Vahid Moghaddasi <mogha...@gmail.com> wrote:

> Hi,
> I have been trying to sort -u the password file /etc/passwd by its
> first field (username) but for some reason sort is giving me a wrong
> result. This is what I used:
> "sort -t : -k 1,1 /etc/passwd" I do not use -u to see the result of the
>
> sort command.
> In the passwd file, I have the first 5 lines copied to the buttom of
> the file (duplicate system accounts, root,daemon,bin,sys,adm with
> different uid,gid's ) I have the users in the middle.

That sounds possibly dangerous or at least confusing. If you try to log
in as one of these accounts, how is the system supposed to which entry
to use. On my system, user names are unique.

> When I sort -u, I would like to see either the top 5 system users or
> the bottom ones but I see one from top, one from the bottom and so on.
> There is no pattern to the output, it seems that -k 1,1 does not have
> any effect at all.

That is two different problems. In my system, I always see the first
entry. This is known as a "stable" sort. The order of identical entries
is preserved. It sounds like you are using an unstable sort algorithm.
Check the man pages for sort and look at the -s option.

-k 1,1 does not appear to have any effect because the default sort uses
the entire line. Therefore it sorts first by the first field, so the
output result is the same. Try "-k 2,2" or "-k 3,3" to see that the -k
is actually working. Also compare the results with "-k 1,1" and then
with "-u -k 1,1" and then with just "-u" to see the effect of -k and -u
together.

> I would appreciate if someone shed a light on this or paste a function
> to do the sort for me.
> I need to sort by username and in another function by UID.

Here is a short program that might be enough to get you started:

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

open( my $fh, '<', '/etc/passwd')
or die("Can't open password file: $!");

my( %users, %uids );
while( (my $line = <$fh>) ) {
next if $line =~ /^#/;
my( $user, $passwd, $uid ) = split(/:/,$line);
$users{$user} = $line unless exists $users{$user};
$uids{$uid} = $line;
}

print "Sorted by user name:\n";
for my $user ( sort keys %users ) {
print "$users{$user}";
}

print "\nSorted by uid:\n";
for my $uid ( sort { $a <=> $b } keys %uids ) {
print "$uids{$uid}";
}


Note that this program will print out the first user name entry. If you
want the last entry instead, remove the 'unless exists $users{$user}'.

Note the '{ $a <=> $b }' in the uid sort that uses a numerical sort
instead of an alphabetical one so that 99 will sort before 100.

Please note that you are expected to post your own program in the
future if you have problems.

Posted Via Usenet.com Premium Usenet Newsgroup Services
----------------------------------------------------------
** SPEED ** RETENTION ** COMPLETION ** ANONYMITY **
----------------------------------------------------------
http://www.usenet.com

John W. Krahn

unread,
Nov 8, 2005, 6:36:59 PM11/8/05
to

Modified from code provided by Randal L. Schwartz:
http://groups-beta.google.com/group/perl.beginners/msg/51a3e9ab2644cd42?hl=en&

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

unless ( @ARGV ) {
# no argument passed, so call ourselves inside vipw:
$ENV{ EDITOR } = $0; # vipw will call us now instead of vi/emacs/whatever
exec 'vipw';
die "Cannot exec vipw: $!";
}

# argument passed means that vipw has called us with a temp filename

# edit it inplace
$^I = '~';
# and all at once (for reasons that are hard to explain here)
$/ = undef;

my %seen;

my @lines = split /\n/, <>; # only one read gets the entire file
# anything we print replaces that entire file
print map "$_\n",
map join( ':', @$_ ),
# sort { $a->[ 2 ] <=> $b->[ 2 ] } # sort by UID
sort { $a->[ 0 ] cmp $b->[ 0 ] } # sort by user name
grep !seen{ $_->[ 0 ] }++,
map [ split /:/ ],
@lines;

__END__


John
--
use Perl;
program
fulfillment

Vahid Moghaddasi

unread,
Nov 8, 2005, 10:36:46 PM11/8/05
to

John W. Krahn wrote:

Thank you John, the link and program was really helpful.

Vahid Moghaddasi

unread,
Nov 8, 2005, 10:47:13 PM11/8/05
to
Jim Gibson wrote:

>
> Here is a short program that might be enough to get you started:
>

El perfecto!
You program is just what I need to add to my over 400 lines of perl
codes. I am not a seasoned perl programmer and trying not use many
system() calls.
Thank you very much Jim for the perfect pointer.
Vahid.

Vahid Moghaddasi

unread,
Nov 8, 2005, 11:03:21 PM11/8/05
to
Jim Gibson wrote:

>
> That sounds possibly dangerous or at least confusing. If you try to log
> in as one of these accounts, how is the system supposed to which entry
> to use. On my system, user names are unique.
>

You are correct, the end result of my program will have unique username
and UID in the password file.


>
> That is two different problems. In my system, I always see the first
> entry. This is known as a "stable" sort. The order of identical entries
> is preserved. It sounds like you are using an unstable sort algorithm.
> Check the man pages for sort and look at the -s option.
>

I did not see -s in the man page on Solaris 9,10, HP-UX11i, AIX 5.2,3
did not check Linux but in any case, the -s must exist on all unix
platform where my program runs.

> -k 1,1 does not appear to have any effect because the default sort uses
> the entire line. Therefore it sorts first by the first field, so the
> output result is the same. Try "-k 2,2" or "-k 3,3" to see that the -k
> is actually working. Also compare the results with "-k 1,1" and then
> with "-u -k 1,1" and then with just "-u" to see the effect of -k and -u
> together.

I am using -k 3,3n and seem to be working fine, I guess -k 1,1 has a
problem on Solaris, HP and AIX, it looks OK on Linux. I wrote a sort
program in C but I would rather user a built-in perl function so I
don't have to keep adding programs to 4000+ unix machines.
>

0 new messages