標準出力に文字列値のリストを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()
}
'