显示列表的不同值和出现次数

显示列表的不同值和出现次数

我有一个程序,它在标准输出上写入一个字符串值列表,每行一个,我想实时显示不同值的列表以及每个值出现的次数。

例如,从此输出:

apple
carrot
pear
carrot
apple

我需要一个生成此输出的命令(最好实时更新):

apple: 2
carrot: 2
pear: 1

任何想法?

答案1

为了扩展 @Bratchley 在评论中所说的内容,如果您将程序的输出打印到文件中,那么您可以在终端中运行 then命令,通过包含如下标志watch来获得近乎实时的输出视图:-n

watch -n 0.1 "cat yourprograms.log | sort | uniq -c | sort -rn"

注意:“-n”标志设置刷新间隔。 “watch”的最短时间是 0.1 秒(或 1/10 秒),而且不能更短。

示例输出:

Every 0.1s: cat yourprograms.log | sort | uniq -c | sort -rn

      6 things
      4 mine
      3 dot
      1 below

包含| sort -rn允许更好的排序视图。按相反的数字顺序sort -rn对 的输出进行排序。uniq -c

如果您只关心前 10 个,则可以包含head如下命令:

watch -n 0.1 "cat yourprograms.log | sort | uniq -c | sort -rn | head"

答案2

这是一个可以完成您想要的功能的小型 Python 2 程序。这些单词按首次出现的时间顺序列出,即每个新单词都添加到列表的底部,但按字母顺序或按出现次数的顺序对单词进行排序会很容易。

输出可能会更整洁一些,例如,如果您知道最大字符串长度,则出现次数可以在一列中对齐。

字数统计.py

#! /usr/bin/env python

''' Real-time word counting

    Written by PM 2Ring 2015.01.29
    From http://unix.stackexchange.com/q/181722/88378
'''

CSI = '\x1b['
clear = CSI + '2J' + CSI + 'H'

def main():
    words = []
    wordcount = {}
    while True:
        try:
            word = raw_input()
        except (KeyboardInterrupt, EOFError):
            print 
            break

        if word not in wordcount:
            words.append(word)
            wordcount[word] = 1
        else:
            wordcount[word] += 1

        print clear
        for word in words:
            print '%s: %d' % (word, wordcount[word])

if __name__ == '__main__':
    main()

要将 的输出通过管道传输yourprog到该程序中,您可以执行以下操作:

yourprog | python wordcount.py

假设它wordcount.py在当前目录中。

或者,授予wordcount.py执行权限(例如chmod a+x wordcount.py)并将其放入命令 PATH 列表中的目录(即执行时列出的目录echo "$PATH")。然后你可以做

yourprog | wordcount.py

你可以在任何地方运行它。

如果您只有 Python 3 而没有 Python 2,则该程序将需要一些小的更改才能运行。

FWIW,这是我为测试上述代码而编写的另一个 Python 脚本。它每 0.5 秒打印一个随机单词,每行一个单词。

随机词.py

#! /usr/bin/env python

import random, time

wordlist = [
    'apple',
    'carrot',
    'pear',
    'orange',
    'banana',
    'cabbage',
    'potato'
]

def main():
    #Time delay between words, in seconds
    delay = 0.5
    while True:
        try:
            print random.choice(wordlist)
            time.sleep(delay)
        except KeyboardInterrupt:
            print 
            break

if __name__ == '__main__':
    main()

您可以运行它,将其输出通过管道传输到wordcount.py如下所示:

python -u randwords.py | python wordcount.py

-u标志告诉 Python 解释器使用无缓冲 I/O。

答案3

简单的 awk 事情。使用一些 ANSI 序列进行移动和清除...

#!/usr/bin/awk -f

BEGIN {
    print "Stats:\n---------------------------------"
}
function clear() {
    for (k in ar)
        printf "\r\033[K\033[1A"
}
function stats() {
    for (k in ar)
        printf "%-10s: %d\n", k, ar[k]
}
/./{
    clear()
    if (!ar[$0])
        ar[$0]=1
    else
        ++ar[$0]
    stats()
}

示例输出生成器:

#!/bin/bash

declare -a fr=(
    apple
    carrot
    pear
)

range=${#fr[@]}

while ((1)); do
    ((x = RANDOM % range))
    printf "%s\n" "${fr[$x]}"
    sleep .5
done

运行为:

$ ./fruit_script | ./awk_script

扩展颜色、隐藏光标等:

#!/bin/bash

quit()
{
    printf "\r\033[K\033[?25h"
}

trap quit SIGINT

awk '
    BEGIN {
        width=3
        printf "\033[?25l"
        print "Stats: (Ctrl-c to quit)\n---------------------------------"
    }
    function clear() {
        for (k in ar)
            printf "\r\033[K\033[1A"
    }
    function stats() {
        for (k in ar)
            printf "\033[0;34m%-*s\033[0m: \033[1;31m%d\033[0m\n", width, k, ar[k]
    }
    /./{
        if (length($0) + 1 > width)
            width=length($0) + 1
        clear()
        if (!ar[$0])
            ar[$0]=1
        else
            ++ar[$0]

        stats()
    }
'

相关内容