Poww
Poww

Reputation: 11

How to print symbols instead of numbers using awk in bash

I have input file

AD;12;qwe
EL;66;qwe
AD;90;oop
AD;8;lpp
EL;56;oop
GR;55;qwe

If I use echo "$file" | awk -F';' '{a[$1]+= 1} END{for(i in a){printf "%-5s: %s\n", i, a[i]}}' | sort

My output will be

AD   : 3
EL   : 2
GR   : 1

But I want to get something like this and I have no idea how to do it

AD   : ###
EL   : ##
GR   : #

Could anyone help me?

Upvotes: 0

Views: 292

Answers (6)

karakfa
karakfa

Reputation: 67507

yet another awk

$ awk -F';' 'function repeat(n,c) 
                 {return (n<=0)?"":(c repeat(n-1,c))} 
                 {a[$1]++} 
             END {for(k in a) printf "%-5s: %s\n",k,repeat(a[k],"#")}' file | sort

AD   : ###
EL   : ##
GR   : #

or with memoization

awk -F';' 'function repeat(n,c) 
               {return (n<=0)?"":(c memoize(n-1,c))}
           function memoize(n,c) 
               {if(!(n in mem)) mem[n]=repeat(n,c); return mem[n]}
               {a[$1]++}
           END {for(k in a) printf "%-5s: %s\n",k,memoize(a[k],"#")}'

with the cost of additional complexity, this should be much faster for large counts

awk -F';' 'function repeat(n,c,   _t_)
               {if(n<=0) return ""; 
                else if(n%2) return c memoize(n-1,c); 
                else {_t_=memoize(n/2,c); return _t_ _t_}}
           function memoize(n,c)
               {if(!(n in mem)) mem[n]=repeat(n,c); return mem[n]}
               {a[$1]++}
           END {for(k in a) printf "%-5s: %s\n",k,memoize(a[k],"#")}' 

Upvotes: 2

Ed Morton
Ed Morton

Reputation: 203655

With GNU awk for gensub():

$ cut -d';' -f1 file | sort | uniq -c |
  awk '{printf "%-5s: %s\n", $2, gensub(/ /,"#","g",sprintf("%*s",$1,""))}'
AD   : ###
EL   : ##
GR   : #

or with any awk:

$ cut -d';' -f1 file | sort | uniq -c |
  awk '{str=sprintf("%*s",$1,""); gsub(/ /,"#",str); printf "%-5s: %s\n", $2, str}'
AD   : ###
EL   : ##
GR   : #

Upvotes: 1

David C. Rankin
David C. Rankin

Reputation: 84559

This is similar to @glennjackman, but the field-width modifier is used to build a string of spaces for output (b) and then converting the spaces to '#' with gsub() rather than using repeat(). You can do:

awk -F';' '
    { a[$1] += 1 } 
    END {
        for (i in a) {
            b = sprintf ("%*s",a[i]," ")
            gsub (/ /,"#",b)
            printf "%-5s: %s\n", i, b
        }
    }
' file | sort

Example Use/Output

$ awk -F';' '
>     { a[$1] += 1 }
>     END {
>         for (i in a) {
>             b = sprintf ("%*s",a[i]," ")
>             gsub (/ /,"#",b)
>             printf "%-5s: %s\n", i, b
>         }
>     }
> ' file | sort
AD   : ###
EL   : ##
GR   : #

They do close to the same thing (but if I'd snapped to the use of repeat() earlier, I'd probably have gone that route :). Let me know if you have questions.

Upvotes: 1

Daweo
Daweo

Reputation: 36520

I want to propose little change to original code in order to get desired result - simply append # in place of keeping count. Let file.txt content be

AD;12;qwe
EL;66;qwe
AD;90;oop
AD;8;lpp
EL;56;oop
GR;55;qwe

then

awk 'BEGIN{FS=";"}{a[$1]=a[$1] "#"}END{for(i in a){printf "%-5s: %s\n", i, a[i]}}' file.txt

output

EL   : ##
AD   : ###
GR   : #

For simplicity sake I left echo and sort parts as these should remain unchanged.

(tested in gawk 4.2.1)

Upvotes: 0

glenn jackman
glenn jackman

Reputation: 246837

A little function

awk -F';' '
  {a[$1] += 1}
  function repeat(char, num,        s) {
      s = sprintf("%*s", num, "")
      gsub(/ /, char, s)
      return s
  }
  END {
    for (i in a)
      printf "%-5s: %s\n", i, repeat("#", a[i])
  }
' file | sort
AD   : ###
EL   : ##
GR   : #

Upvotes: 4

Raman Sailopal
Raman Sailopal

Reputation: 12877

echo "$file" | awk -F';' '{a[$1]+= 1} END{ for(i in a){ printf "%s : ",i;for (j=1;j<=a[i];j++) { printf "%s","#" } printf "\n", i, a[i]}}' | sort

Print the index of the array and then process another loop from 1 to the value of the index, printing "#"

Using GNU awk and utilising array sorting to negate the need to pipe through to sort

echo "$file" | awk -F';' '{a[$1]+= 1} END{ PROCINFO["sorted_in"]="@val_num_desc";for(i in a){ printf "%s : ",i;for (j=1;j<=a[i];j++) { printf "%s","#" } printf "\n", i, a[i]}}'

Upvotes: 1

Related Questions