一意の値とリストの発生を表示します。

一意の値とリストの発生を表示します。

標準出力に文字列値のリストを1行に1つずつ作成するプログラムがありますが、各値が発生した回数とともに様々な値のリストをリアルタイムで表示したいと思います。

たとえば、次の出力から:

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」フラグは更新間隔を設定します。 「時計」の最小時間は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プログラムがあります。単語は最初に現れる順序でリストされます。つまり、各新しい単語がリストの下部に追加されますが、単語をアルファベット順または出現回数の順に並べ替えるのは簡単です。

出力が少しきれいになることがあります。たとえば、最大文字列の長さがわかっている場合、項目は1つの列に並べ替えることができます。

単語数.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秒ごとに1行に1単語ずつランダムな単語を印刷します。

ランダムな単語。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

単純な奇妙なもの。移動と削除には、いくつかの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()
    }
'

関連情報