Beefy Boxes and Bandwidth Generously Provided by pair Networks
XP is just a number
 
PerlMonks  

Evolution of an Obfuscated Throwaway Script

by neshura (Chaplain)
on Oct 06, 2000 at 04:37 UTC ( [id://35503]=obfuscated: print w/replies, xml ) Need Help??

Well, they jest don't work me all that hard here at my happy company, so when a coworker approached and asked if I could write him a quick script to format the output of bdf so he could import it into Excel, I said "Abso-positively, homedude! I've got 8 hours to kill!"

So what's this bdf thing? Read the man page for more details. All I knew was that he tried to capture the output from the screen and paste it into Excel, but the formatting was just ALL wrong. He gave me a sample of the normal screen output from bdf.

Filesystem kbytes used avail %used Mounted on /dev/vg00/lvol3 143360 45210 92038 33% / /dev/vg00/lvol1 83733 29494 45865 39% /stand /dev/vg00/lvol8 2048000 820619 1150910 42% /var
and also a sample of the fnarky output.
Filesystem kbytes used avail %used Mounted on i47ebfl2:/mnt/home2 51249152 34195824 16920184 67% /nfs/home2 i47ebfl1:/mnt/home1 51249152 27468376 23595000 54% /nfs/home1 i47ebfl1:/mnt/home 262144 1496 244640 1% /nfs/home
I wanted to do it in a one-liner originally, so I could impress "Joe" with my Perl knowledge. Unfortunately, I haven't had occasion to use all the marvelous tools such as map and grep and so on. I decided just to try and get something that functioned first. So I pulled out my dusty Camel 2 and started coding.

It took me a while -- I started with about 16 or 18 lines, and there was an annoying little bug which resulted in some empty cells in the final CSV output. I fixed said bug with a grep on /./. What follows was my proud presentation to the occupants of #perlmonks, without the newlines or comments.

# pipe output from bdf through this script for a surprise @lines = <>; { if (scalar(@tokens = split /\s+/, (shift @lines)) > 1) { } else { push @tokens, (grep /./, (split /\s+/, (shift @lines))); } push @csv, ((join ',', @tokens) . "\n"); redo if @lines; } print @csv;
Doh! Thanks zdog, I COULD have done (scalar...) || (push...). Quoth zdog, "I picked it up reading 'jcwren code'". Excellent. Let's put it on one line.
@lines = <>; { (scalar(@tokens = split /\s+/, (shift @lines)) > 1) || +push @tokens, (grep /./, (split /\s+/, (shift @lines))); push @csv, ( +(join ',', @tokens) . "\n"); redo if @lines; } print @csv;
Well this works fine. So I send it to "Joe", and his eyes get wide and I just grin and say "It works. Try it." I caution him that it doesn't work if there are spaces in the names of the filesystems. It's not really robust, but then, he didn't give me a lot of data. So Joe is satisfied. But I'm not, and I've got three hours before I can leave.

So the next step is to clean out the parens and the unnecessary functions. Like scalar. Don't even remember why I used scalar. Insurance I guess. And then there is substituting "or" for || so I can get rid of some more parens.

@lines = <>; { (@tokens = split /\s+/, shift @lines) > 1 or push @toke +ns, grep /./, split /\s+/, shift @lines; push @csv, (join ',', @token +s) . "\n"; redo if @lines; } print @csv;
This is great! The marginal value to my company of these code improvements is actually negative, and falling rapidly. The final task is to take some hints from posts by japhy. I use odd delimiters for quoting. I get rid of whitespace. I use one-letter variable names. The final version, which is as far as I can take it, is as follows:
@i=<>;{(@w=split /\s+/,shift @i)>1 or push @w,grep /./,split /\s+/,shi +ft @i; push @c,(join q;,;,@w).qq.\n.;redo if @i;}print @c
which gave the desired output
/dev/vg01/lvol2,8257536,158029,7593289,2%,/mnt/ims_logs /dev/vg01/lvol1,16384000,13542344,2755462,83%,/mnt/ims i47ebfl2:/mnt/home2,51249152,34196640,16919376,67%,/nfs/home2 i47ebfl1:/mnt/home1,51249152,27468600,23594776,54%,/nfs/home1
In summary, this was a throwaway script. I would never intentionally obfuscate any code that someone would have to come along and maintain later. This was the first occasion I've ever had to do a little obfuscation, but I would never have tried to do it if it weren't for one original design factor. Namely, the fact that using a block with redo was (in this case) better than using the usual for or foreach. Said block confused a fellow programmer for a bit.

So now I've had my first taste of obfuscation. Honestly? It was a so-so experience. I taught myself some new constructs, with the help of zdog, jlp, h0mee, and also jcwren and japhy. But I think I like solving useful problems a lot better, and will stick with functional (non-JAPH) readable scripts for the time being.


So go ahead -- what would you have done differently? How? Why?

e-mail neshura

Replies are listed 'Best First'.
(bbq) RE: Evolution of an Obfuscated Throwaway Script
by BBQ (Curate) on Oct 06, 2000 at 08:02 UTC
    Okay, so this is really NOT obfuscated, but it is a one liner!
    # 1st shot df -h | perl -e '@i = <>;s/(\ +)/\,/g && print for @i[1..@i];' > the.c +sv # 2nd shot df -h | perl -e '/^\w/&&next||s/\ +/\,/g&print for<>' > the.csv
    I kinda like the look, but merlyn has already pointed out that s/// for is bad. :)

    #!/home/bbq/bin/perl
    # Trust no1!
      df -h | perl -lpe 's/\s+/,/g' > the.csv
      FORE!

      Sorry, I know it's supposed to be obfuscated, but I can't resist the urge to golf. :)

      -Matt

        I would definitly stand up and clap if it weren't for one small detail. The first line in this case would read:
        Filesystem,Size,Used,Avail,Use%,Mounted,on

        Yeah, I know... I'm being a picky sore looser! :)

        #!/home/bbq/bin/perl
        # Trust no1!
      where did merlyn point out that the s/// for is bad? why is this?
        Yeah, just where did I point out that that was bad?

        And remember, I have different rules for Obfuscated vs. Golf vs. Bowling vs. 10-minute hacks vs. actual code that a customer paid for vs. training materials. Don't paint me with a broad sword there, or something like that.

        -- Randal L. Schwartz, Perl hacker

RE: Evolution of an Obfuscated Throwaway Script
by frankus (Priest) on Oct 06, 2000 at 18:22 UTC

    I used to feel guilt about tinkering about finding solutions in this manner until I found this in the Sed & Awk book, I feel it's sentiments apply equally to Perl:

    <quote>"For some people, myself included, the satisfaction of solving a problem is the difference between work and drudgery. Given the choice of using vi or sed to make a series of repeated edits over a number of files, I will choose sed, simply because it makes the problem more interesting to me. I am refining a solution instead of repeating a series of keystrokes."</quote>

    To summarise: go forth and hack with impunity!

    -- 
    
    
    Brother Frankus.
      I recall reading this... and while I agree with the sentiment, I think it sells vi short. Part of what I love about working with Vim is that is has the raw ingredients for you to cook up interesting, rather than menial, solutions. Perhaps more so than sed, though to state so affirmatively is more than my knowledge of each will allow.
        One of the more interesting vi macros I've seen is one that solves the 'Tower of Hanoi'. I believe it comes as an example for vim (the Linux vi). Jano's Vim Marcro Page has some other good ones.

        /\/\averick

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: obfuscated [id://35503]
Approved by root
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others exploiting the Monastery: (3)
As of 2024-04-20 02:06 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found