고유한 값과 목록의 발생을 표시합니다.

고유한 값과 목록의 발생을 표시합니다.

표준 출력에 문자열 값 목록을 한 줄에 하나씩 작성하는 프로그램이 있는데, 각 값이 발생한 횟수와 함께 다양한 값 목록을 실시간으로 표시하고 싶습니다.

예를 들어, 다음 출력에서:

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 프로그램이 있습니다. 단어는 처음 나타나는 순서대로 나열됩니다. 즉, 각각의 새로운 단어가 목록의 맨 아래에 추가되지만 단어를 알파벳순이나 발생 횟수 순으로 정렬하는 것이 쉽습니다.

출력이 좀 더 깔끔해질 수 있습니다. 예를 들어 최대 문자열 길이를 알고 있으면 항목이 하나의 열에 정렬될 수 있습니다.

단어 개수.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

단순한 이상한 것. 이동 및 삭제를 위해 일부 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()
    }
'

관련 정보