Re: Golf: reverse sort /etc/passwd by UID
by tobyink (Canon) on Feb 05, 2013 at 16:56 UTC
|
perl -e'print$_->[0]for sort{$b->[3]-$a->[3]}map[$_,split/:/],<>' /etc
+/passwd
With additional whitespace, that's...
perl -e'print $_->[0] for sort { $b->[3] - $a->[3] } map [$_, split /:
+/], <>' /etc/passwd
package Cow { use Moo; has name => (is => 'lazy', default => sub { 'Mooington' }) } say Cow->new->name
| [reply] [Watch: Dir/Any] [d/l] [select] |
|
| [reply] [Watch: Dir/Any] |
Re: Golf: reverse sort /etc/passwd by UID
by moritz (Cardinal) on Feb 05, 2013 at 18:17 UTC
|
Here's a Perl 6 solution, works with current Rakudo. Not really golfed, just the way you'd write it in a terse way:
$ cat /etc/passwd | perl6 -e '.say for lines.sort: +*.split(":")[2]'
The nice part is that Perl 6's sort method automatically does the Schwartzian transform for you if the comparison code object takes only one argument.
| [reply] [Watch: Dir/Any] [d/l] |
Re: Golf: reverse sort /etc/passwd by UID
by BrowserUk (Patriarch) on Feb 05, 2013 at 17:11 UTC
|
## typos (see below) corrected
perl -E"say reverse sort{/(:\d+:)/<=>/(:\d+:)/}<>" /etc/passwd
(Maybe not if usernames can be all digits?)
With the rise and rise of 'Social' network sites: 'Computers are making people easier to use everyday'
Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
"Science is about questioning the status quo. Questioning authority".
In the absence of evidence, opinion is indistinguishable from prejudice.
| [reply] [Watch: Dir/Any] [d/l] |
|
Does this work?
perl -E"say reverse sort{/(:\d+:)/<=>/(:\d+:)/}<>" /etc/passwd
No, it does not work.
In the sort compare function the current records are in $a and $b but you are not accessing the current record in your example.
The comparison operator <=> puts its operands into scalar context and the match operator in scalar context returns TRUE or FALSE so you are not comparing the contents of the capturing parentheses.
| [reply] [Watch: Dir/Any] [d/l] [select] |
|
| [reply] [Watch: Dir/Any] |
|
|
|
| [reply] [Watch: Dir/Any] [d/l] [select] |
|
D'oh! I did omit a couple of bits didn't I (It was (obviously) untested -- I don't have an /etc/passwd).
I tried to remove the $b=~ & $a=~ bits when I noticed that reverse was one character less -- ignoring/forgetting that $_ cannot be both at the same time :(.
I don't think the (...)[0] bits are necessary, without /g only the regex will only return one (the first) match.
This should work? (still untested):
perl -E"say sort{$b=~/:(\d+):/<=>$a=~/:(\d+):/}<>" /etc/passwd
With the rise and rise of 'Social' network sites: 'Computers are making people easier to use everyday'
Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
"Science is about questioning the status quo. Questioning authority".
In the absence of evidence, opinion is indistinguishable from prejudice.
| [reply] [Watch: Dir/Any] [d/l] [select] |
|
|
|
|
It's quite possible that I'm being exceedingly dense, but how is this any different from just:
perl -E"say reverse<>" /etc/passwd
UPDATE- we only wanted it to work as described below-- with implicit reassignment of $_ to $a and also to $b.
It's not the same. BrowserUK's solution uses two regexes, each with a capture group. The capture groups implicitly assign to what would be the equivalents of "$a" and "$b". Since the point of this excercise was to save typing (potentially at the loss of clarity), BrowserUK didn't bother wasting precious keystrokes in explicitly assigning the result of the regex capture groups to an "$a" or "$b". Instead, he/she (I don't know BrowserUK personally) just let Perl handle those details. BrowserUK definitely meant what was posted ;~)
Tommy
A mistake can be valuable or costly, depending on how faithfully you pursue correction
| [reply] [Watch: Dir/Any] [d/l] |
|
UPDATE- as thundergnat correctly points out, the code doesn't work as first intended, at least not without some modification.
Technically it's *possible* that usernames can be completely numeric, but that's outright abusive--borderline illegal, and definitely prone to all kinds of problems.
If I we were dealing with "abusive" uid's, it wouldn't be too hard to add a neg look-behind assertion.
Now, for the meat and potatoes... I did run into some small typos in your code, but after correcting them, it worked. *slow and dramatic golf clap*. I had a hunch it could be done with regexes!! I've said it before, and I'll say it again... you have a dark gift my friend (sarcasm).
[user@host]$ perl -e 'print reverse sort{/(:\d+:))/<=>/(:\d+:/)}<>' /e
+tc/passwd
Unmatched ) in regex; marked by <-- HERE in m/(:\d+:)) <-- HERE / at -
+e line 1.
[user@host]$ perl -e 'print reverse sort{/(:\d+:)/<=>/(:\d+:/)}<>' /et
+c/passwd
Unmatched ( in regex; marked by <-- HERE in m/( <-- HERE :\d+:/ at -e
+line 1.
[user@host]$ perl -e 'print reverse sort{/(:\d+:)/<=>/(:\d+:)/}<>' /et
+c/passwd
...and AWESOMENESS HAPPENS ALMOST HAPPENED!
Read through the rest of the thread for the reason why this awesome snippet didn't quite work as intended...
Tommy
A mistake can be valuable or costly, depending on how faithfully you pursue correction
| [reply] [Watch: Dir/Any] [d/l] |
Re: Golf: reverse sort /etc/passwd by UID
by MidLifeXis (Monsignor) on Feb 06, 2013 at 14:22 UTC
|
# 1 2 3 4 5
# 123456789012345678901234567890123456789012345678901
print sort{($x,$y)=(split(":",$a.$b))[2,8];$y-$x}<>
First-ever golf, has to be a better solution.
| [reply] [Watch: Dir/Any] [d/l] |
|
# 1 2 3 4
# 1234567890123456789012345678901234567890123
perl -e'print sort{@x=split":",$a.$b;$x[8]-$x[2]}<>' /etc/passwd
Or even:
# 1 2 3 4
# 123456789012345678901234567890123456789012
perl -e'print sort{(@x=split":",$a.$b)[8]-$x[2]}<>' /etc/passwd
Update: or with a sufficiently outdated Perl...
# 1 2 3 4
# 1234567890123456789012345678901234567890
perl5.8.9 -e'print sort{split":",$a.$b;$_[8]-$_[2]}<>' /etc/passwd
(split in void context was deprecated in 5.10 and dropped in 5.12 IIRC.)
package Cow { use Moo; has name => (is => 'lazy', default => sub { 'Mooington' }) } say Cow->new->name
| [reply] [Watch: Dir/Any] [d/l] [select] |
|
| [reply] [Watch: Dir/Any] [d/l] |
|
| [reply] [Watch: Dir/Any] |
|
That. Was. Awesome.
++MidLifeXis
Tommy
A mistake can be valuable or costly, depending on how faithfully you pursue correction
| [reply] [Watch: Dir/Any] |
Re: Golf: reverse sort /etc/passwd by UID
by tobyink (Canon) on Feb 06, 2013 at 10:23 UTC
|
OK, using salva's wonderful Sort::Key, I can go five characters shorter...
perl -MSort::Key=rikeysort -e'print rikeysort{/(\d+)/;$1}<>' /etc/pass
+wd
If you don't mind a spurious blank line at the end of the output, then it's easy to drop another two characters...
perl -MSort::Key=rikeysort -E'say rikeysort{/(\d+)/;$1}<>' /etc/passwd
package Cow { use Moo; has name => (is => 'lazy', default => sub { 'Mooington' }) } say Cow->new->name
| [reply] [Watch: Dir/Any] [d/l] [select] |
Re: Golf: reverse sort /etc/passwd by UID
by choroba (Cardinal) on Feb 06, 2013 at 15:29 UTC
|
Only suitable for a terminal, not to be redirected to a file:
# 1 2 3 4
# 12345678901234567890123456789012345678901234
perl -e 'print sort map 9/(1+(split/:/)[2])."\r$_",<>' /etc/passwd
| [reply] [Watch: Dir/Any] [d/l] |
|
1.52590218966964e-05\rnobody:x:65534:65534:nobody:/nonexistent:/bin/sh
And thus gets sorted after root.
package Cow { use Moo; has name => (is => 'lazy', default => sub { 'Mooington' }) } say Cow->new->name
| [reply] [Watch: Dir/Any] [d/l] |
|
OK, just change 1/ to 9/ (or 8 or 7). Updated.
| [reply] [Watch: Dir/Any] [d/l] [select] |
|
| [reply] [Watch: Dir/Any] |
|
| [reply] [Watch: Dir/Any] |
|
|
|
| [reply] [Watch: Dir/Any] [d/l] |