Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to horizontally mirror ascii art?

So ... I know that I can reverse the order of lines in a file using tac or a few other tools, but how do I reorder in the other dimension, i.e. horizontally? I'm trying to do it with the following awk script:

{
    out="";
    for(i=length($0);i>0;i--) {
        out=out substr($0,i,1)}
    print out;
}

This seems to reverse the characters, but it's garbled, and I'm not seeing why. What am I missing?

I'm doing this in awk, but is there something better? sed, perhaps?

Here's an example. Input data looks like this:

$ cowsay <<<"hello"
 _______
< hello >
 -------
        \   ^__^
         \  (oo)\_______
            (__)\       )\/\
                ||----w |
                ||     ||

And the output looks like this:

$ cowsay <<<"hello" | rev
_______ 
> olleh <
------- 
^__^   \        
_______\)oo(  \         
\/\)       \)__(            
| w----||                
||     || 

Note that the output is identical whether I use rev or my own awk script. As you can see, things ARE reversed, but ... it's mangled.

like image 701
Graham Avatar asked Oct 28 '12 20:10

Graham


1 Answers

rev is nice, but it doesn't pad input lines. It just reverses them.

The "mangling" you're seeing is because one line may be 20 characters long, and the next may be 15 characters long. In your input text they share a left-hand column. But in your output text, they need to share a right-hand column.

So you need padding. Oh, and asymmetric reversal, as Joachim said.

Here's my revawk:

#!/usr/bin/awk -f

# 
length($0)>max {
    max=length($0);
}

{
    # Reverse the line...
    for(i=length($0);i>0;i--) {
        o[NR]=o[NR] substr($0,i,1);
    }
}

END {
    for(i=1;i<=NR;i++) {
        # prepend the output with sufficient padding
        fmt=sprintf("%%%ds%%s\n",max-length(o[i]));
        printf(fmt,"",o[i]);
    }
}

(I did this in gawk; I don't think I used any gawkisms, but if you're using a more classic awk variant, you may need to adjust this.)

Use this the same way you'd use rev.

ghoti@pc:~$ echo hello | cowsay | ./revawk | tr '[[]()<>/\\]' '[][)(><\\/]'
                    _______ 
                   < olleh >
                    ------- 
            ^__^   /        
    _______/(oo)  /         
/\/(       /(__)            
   | w----||                
   ||     ||                

If you're moved to do so, you might even run the translate from within the awk script by adding it to the last printf line:

        printf(fmt," ",o[i]) | "tr '[[]()<>/\\]' '[][)(><\\/]'";

But I don't recommend it, as it makes the revawk command less useful for other applications.

like image 152
ghoti Avatar answered Oct 11 '22 05:10

ghoti