http://www.perlmonks.org?node_id=932280

This is more of a success story than a CUFP, but I had to share.

I've been learning and using Perl more or less since I signed up to PM (so, 18 days or so), though a programmer for some time longer. Still, this was a nice way to validate to myself that I could use it for some "off the cuff" tasks.

A coworker asked me (as the resident Vim guru) if I knew a Vim trick that would quickly convert an Erlang term in an error log he was reading into something readable. For those who don't know, Erlang has a funny way of doing strings: it doesn't! A list of integers which are all printable ASCII (e.g. [65,66,67]) will be pretty-printed as "ABC", and any list where at least one element isn't printable will be rendered as a list instead. That means, for example, that a single Unicode character will make your entire string print as a nice long list of numbers.

Lists are stored as cons cells in Erlang; i.e. not very efficiently for strings, so they also have a "binary string", which more like normally malloced buffer of bytes with known length. They're pretty-printed as <<"hello">>, or again, <<65, 10, 192>> if there are unprintables.

In the situation that unfolded at work, we had the full HTML of a webpage being spewed out in a debug log, except some stranger characters caused the entire thing to print as a very long list of numbers (which didn't do wonders for debugging). Thus my Vim skills were consulted -- and honestly, I had no idea with Vim. But Vim and Perl?

:'<,'>!perl -pe 'chomp; $_ =~ s/[<>]*//g; $_ = join "", map { chr $_ } split ",", $_'

Voilà! HTML came spewing onto the page. I was so happy that I got it on the first try. :) On reflection, map chr, split "," would have worked just as well. Next time!

Anne

Edit: on reflection, how about :'<,'>!perl -ne 'print join "", map chr, split ",", s/[<>]*//gr'? I didn't need chomp after all!

Replies are listed 'Best First'.
Re: A little win (pack)
by tye (Sage) on Oct 19, 2011 at 05:59 UTC

    join "", map chr is like rolling your own version of pack "C*" (Unicode variations left as an exercise for the reader).

    - tye        

      Thank you! That condenses it a bit; I need to pay more attention to pack and unpack, I probably end up re-inventing them more often than I care to admit.

Re: A little win
by jwkrahn (Abbot) on Oct 19, 2011 at 07:25 UTC
    :'<,'>!perl -pe 'chomp; $_ =~ s/[<>]*//g; $_ = join "", map { chr $_ } + split ",", $_'

    Could be written more simply and efficiently as:

    :'<,'>!perl -pe 'chomp; tr/<>//d; $_ = join "", map chr, split /,/'

      Combine that with tye's suggestion and we're down to:

      :'<,'>!perl -pe 'tr/<>//d; $_ = pack "C*", split ","'

        Please read perldoc -f split, as the first argument to split is usually a regex, not a string

        :'<,'>!perl -pe 'tr/<>//d;$_=pack"C*",split/,/'

        Enjoy, Have FUN! H.Merijn