Mainly Tech projects on Python and Electronic Design Automation.

Friday, April 11, 2008

That history meme, in Python!

It seemsed that everyone was joining in the 'history meme', and finding
out what was in their history:

href="http://blogs.gnome.org/newren/2008/04/11/that-history-meme/">http://blogs.gnome.org/newren/2008/04/11/that-history-meme/

href="http://jaysonrowe.wordpress.com/2008/04/11/command-history-meme/">http://jaysonrowe.wordpress.com/2008/04/11/command-history-meme/

href="http://jjesse.wordpress.com/2008/04/11/joining-the-history-meme/">http://jjesse.wordpress.com/2008/04/11/joining-the-history-meme/

href="http://fengshaun.wordpress.com/2008/04/11/shell-history-meme/">http://fengshaun.wordpress.com/2008/04/11/shell-history-meme/

(You get the idea, ... more href="http://blogsearch.google.co.uk/blogsearch?hl=en&ie=UTF-8&q=%22history+meme%22&btnG=Search+Blogs">here).




They were all using unix command line tools, piped together to show the
most frequent commands they had used.:


history|awk '{a[$2]++ } END{for(i in a){print a[i] " " i}}'|sort -rn|head




This being a Python blog, and knowing before-hand that Python is really
awful at one-liners, I nevertheless decided that it would be of some
use to try and pipe history to a Python one-liner that performed a
similar task .



I came up with:


bash$ history | python  -c 'import sys,itertools,pprint;  style="font-family: Courier New,Courier,monospace;"> style="font-family: Courier New,Courier,monospace;">    pprint.pprint(sorted style="font-weight: bold; color: rgb(0, 0, 153);">([ style="font-family: Courier New,Courier,monospace;"> style="font-family: Courier New,Courier,monospace;">        (len(list(g)),k) for k,g in itertools.groupby(sorted style="font-weight: bold; color: rgb(153, 51, 153);">([
x.split()[1]for x in sys.stdin if len(x.split())>1 style="font-weight: bold; color: rgb(153, 51, 153);">])
, lambda x:x) style="font-family: Courier New,Courier,monospace;"> style="font-family: Courier New,Courier,monospace;"> style="font-weight: bold; color: rgb(0, 0, 153);">]) style="font-family: Courier New,Courier,monospace;"> style="font-family: Courier New,Courier,monospace;"> [-10:][::-1])' style="font-family: Courier New,Courier,monospace;"> style="font-family: Courier New,Courier,monospace;">[(63, 'echo'), style="font-family: Courier New,Courier,monospace;"> style="font-family: Courier New,Courier,monospace;"> (41, 'history'), style="font-family: Courier New,Courier,monospace;"> style="font-family: Courier New,Courier,monospace;"> (30, './tst1.sh'), style="font-family: Courier New,Courier,monospace;"> style="font-family: Courier New,Courier,monospace;"> (28, 'declare'), style="font-family: Courier New,Courier,monospace;"> style="font-family: Courier New,Courier,monospace;"> (21, 'python'), style="font-family: Courier New,Courier,monospace;"> style="font-family: Courier New,Courier,monospace;"> (18, 'perl'), style="font-family: Courier New,Courier,monospace;"> style="font-family: Courier New,Courier,monospace;"> (18, 'cat'), style="font-family: Courier New,Courier,monospace;"> style="font-family: Courier New,Courier,monospace;"> (16, 'ls'), style="font-family: Courier New,Courier,monospace;"> style="font-family: Courier New,Courier,monospace;"> (15, 'xterm'), style="font-family: Courier New,Courier,monospace;"> style="font-family: Courier New,Courier,monospace;"> (15, 'history|python')] style="font-family: Courier New,Courier,monospace;"> style="font-family: Courier New,Courier,monospace;">bash$


I decided to break the command into multiple lines for readability
above; it was developed, painfully, all on one line.



So readers, the above is something that Python stinks at - one-liners.
(Unless you know a better way in Python ...)



- Paddy.

6 comments:

David Goodger said...

You don't need the "lambda x:x". itertools.groupby defaults to the identity function for the key. That makes it a bit shorter!

fawcett said...

You might like my pyline script, which I wrote to make Python work well in command pipelines. I use it all the time, and it's one of the first things I install on a new Unix box.

Paddy3118 said...

Hi David,
Someone actually read that god-awful mess that I wrote - to such a degree that they understood it?!?!
Thanks for correction. I had not known that about groupby. (I have gone from reading about it and thinking that I will never use it - it must be there for completeness sake, to using groupby several times).

Hi fawcett,
I had seen pyline before but my post was just to show Pythons limitations. I do know my way around standard Unix tools, as well as Perl and AWK and tend to use them for my huge one-liners :-)

- Paddy.

Paddy3118 said...

P.S.
The two list comprehensions could be replaced by generator expressions but they stayed as it was easier to find my way around the line with the occasional ']' or '[' to 'anchor' me when reading the mush.

- Paddy.

Justin said...

python isn't that bad, if you have helper modules lying around...

history | python -c 'import sys,pprint,count;
pprint.pprint(count.count(x.split()[1] for x in sys.stdin)[:10])'

works for me :)

Paddy3118 said...

Hi Justin,
You just got me scrambling off searching for this unknown count module - which turns out to not be a standard module, which I guess is your point.

No pulling magic bunnies out of a hat! :-)


- Paddy.

Post a Comment

About Me

Followers

Subscribe Now: google

Add to Google Reader or Homepage

Go deh too!

whos.amung.us

Blog Archive