【问题标题】:AWK Beginner Bar Graph/HistogramAWK 初学者条形图/直方图
【发布时间】:2018-07-31 12:32:02
【问题描述】:

我被合法地分配了这个提示作为我的第一个真正的awk 程序,我什至不知道从哪里开始。任何入门帮助将不胜感激。

编写一个名为hist.awk 的awk 程序,该程序读取一个数字文件并打印出现次数的直方图。对于如下所示的输入:

1
4
5
0
2
4
6
8
1
3
2
4
6
7
2
3
3
4
4

输出将是:

0:        1 ***
1:        2 ******
2:        3 ********
3:        3 ********
4:        5 **************
5:        1 ***
6:        2 ******
7:        1 ***
8:        1 ***

第一列包含文件中的数字。第二个包含该数字出现的次数。该图显示了总数的百分比,缩放为 50,因此 50 个星号表示 100%,25 个星号表示 50%,依此类推。

【问题讨论】:

  • 欢迎来到 Stack Overflow,请将您的示例包装在 CODE TAGS 中。

标签: linux unix awk terminal


【解决方案1】:

您能否尝试关注awk,如果这对您有帮助,请告诉我(尽管我仍然不确定您的* 是否在输出中打印)。

awk 'function astrick_printing(var){;num=val=count="";count=((var*100)/50);while(++num<=count){val=val "*"};return val;} {a[$0]++} END{for(i in a){print i,a[i],astrick_printing(a[i])}}'  Input_file | sort

现在也添加上述解决方案的非一种线性形式:

awk '
function astrick_printing(var){
  num=val=count="";
  count=((var*100)/50);
  while(++num<=count){
    val=val "*"};
  return val
}
{
  a[$0]++
}
END{
  for(i in a){
    print i,a[i],astrick_printing(a[i])}
}
'  Input_file | sort

输出如下:

0 1 **
1 2 ****
2 3 ******
3 3 ******
4 5 **********
5 1 **
6 2 ****
7 1 **
8 1 **

【讨论】:

    【解决方案2】:

    另一个awk

     $ awk '{a[$1]++; c++} 
         END{for(k in a) 
               {s=sprintf("%*s",a[k]*50/c,FS); 
                gsub(FS,"*",s); 
                print k":", a[k], s}}' file
    
    
    0: 1 **
    1: 2 *****
    2: 3 *******
    3: 3 *******
    4: 5 *************
    5: 1 **
    6: 2 *****
    7: 1 **
    8: 1 **
    

    【讨论】:

      【解决方案3】:

      以下awk 行执行请求:

      • 它会对计数进行适当的四舍五入以获得正确的星数(4.5 星 => 5 星,4.2 星 => 4 星)
      • 它在内存中有一个 50 * 的字符串,并且只打印需要的部分。它使用格式说明符 .ws 执行此操作,其中 w 替换为 int(a[i]*50/c+0.5)
      • 它记录最小和最大的数字。任何未出现在该范围内的数字都将被打印为 0 星。

      脚本如下:

      awk 'BEGIN{imin=+999999;imax=-99999;
                 stars="**************************************************"
           }
           {a[$1]++;imin=$i<imin?$i:imin; imax=$i>imax?$i:imax}
           END{ for(i=imin;i<=imax;i++) 
                   printf "%3d: %-4d %.*s\n",i,a[i],int(a[i]*50/NR+0.5),stars    
           }' file.txt
      

      和输出:

        0: 1    ***
        1: 2    *****
        2: 3    ********
        3: 3    ********
        4: 5    *************
        5: 1    ***
        6: 2    *****
        7: 1    ***
        8: 1    ***
      

      一切都基于printf format modifiers。要打印的格式为

      %3d: %-4d %.*s\n
      

      内容如下:

      • (%3d) 打印一个宽度为 3 的整数
      • (-4d) 打印一个左对齐宽度为 4 的整数
      • (%.*s) 是%.ws 的变体,表示打印字符串的第一个w 字符。 w 的值(由* 表示)是从参数列表中获取的。

      如果您不关心列表中没有出现的数字(例如,您的文件有 10 但没有 9,那么上面将有一行 9: 0 作为输出。如果您不关心这个,那么你可以这样做:

      awk 'BEGIN{ PROCINFO["sorted_in"]="@ind_num_asc"
                  stars="**************************************************" }
           {a[$1]++}
           END{ for(i in a) 
                    printf "%3d: %-4d %.*s\n",i,a[i],int(a[i]*50/NR+0.5),stars
           }' file.txt
      

      需要PROCINFO["sorted_in"]="@ind_num_asc" 来确保有序遍历a 的索引。然而,这是一个gawk extension

      【讨论】:

      • 你可以使用printf("%3d: %-4d %.*s\n",i,a[i],a[i]*50/NR,"********")
      • 是的,我知道,但我不确定哪个更令人困惑,* 或直接注入 a[i]
      • %.*s ,没有字符,然后是要打印的字符 ++
      • awk '{a[$1]++}END{for(i in a)printf("%3d: %-4d %.*s\n",i,a[i],a[i]*50/NR,"************************") | "sort"}' file
      • @AkshayHegde 更新,并添加了for(i in a)。请注意,这不会显示空垃圾箱。使用PROCINFO["sorted_in"]="@ind_num_asc" 删除排序
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-01-16
      • 1970-01-01
      • 1970-01-01
      • 2019-02-23
      相关资源
      最近更新 更多