Reputation: 11
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
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
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
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
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
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
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