각 캐릭터의 발생 횟수를 계산하는 방법은 무엇입니까?


13

예를 들어 다음과 같은 파일 1.txt이 있습니다.

Moscow
Astana
Tokyo
Ottawa

모든 문자 수를 다음과 같이 계산하고 싶습니다.

a - 4,
b - 0,
c - 1,
...
z - 0

4
받아 들여진 대답에서 완전히 명확하지는 않습니다. "A"와 "a"를 구별 하시겠습니까? 당신의 질문은 당신을 제안합니다.
Jacob Vlijm

답변:


20

이것을 사용할 수 있습니다 :

sed 's/\(.\)/\1\n/g' 1.txt | sort | uniq -ic
  4  
  5 a
  1 c
  1 k
  1 M
  1 n
  5 o
  2 s
  4 t
  2 w
  1 y

sed부분은 모든 문자 뒤에 줄 바꿈을 배치합니다. 그 다음 sort순으로 OUPUT. 그리고 마지막 uniq으로 발생 횟수를 계산합니다. 대소 문자를 구분하지 않으려면 의 -i플래그를 uniq생략 할 수 있습니다.


3
훌륭합니다. 또 다른주의 사항은 출력을 다시 sort -k 2알파벳 순으로 나열하는 것입니다.
tetris11

3
이것은 가장 짧은 방법, 가장 이해하기 쉽지만 불행히도 가장 느리다
c0rp

Mac OS XI sed -e $'s/\(.\)/\\1\\\n/g'에서는 stackoverflow.com/a/18410122/179014 참조 )
asmaier

발생 횟수 (내림차순)로 주문하려면 : | sort -rnk 1. 그리고 만약 당신이 매우 큰 파일을 다루는 경우, 당신은 실제 수에 대한 프록시를 얻기 위해 수천 줄을 샘플링 할 수 있습니다.cat 1.txt | shuf -n 10000 | sed 's/\(.\)/\1\n/g' | sort | uniq -ic | sort -rnk 1
cpury

6

조금 늦었지만 세트를 완성하기 위해 또 다른 python (3) 접근 방식은 다음과 같이 정렬되었습니다.

#!/usr/bin/env python3
import sys

chars = open(sys.argv[1]).read().strip().replace("\n", "")
[print(c+" -", chars.count(c)) for c in sorted(set([c for c in chars]))]

A - 1
M - 1
O - 1
T - 1
a - 4
c - 1
k - 1
n - 1
o - 4
s - 2
t - 3
w - 2
y - 1

설명

  1. 파일을 읽고 공백을 건너 뛰고 "문자"로 반환합니다.

    chars = open(sys.argv[1]).read().strip().replace("\n", "")
  2. 고유 한 (정렬 된) 고유 세트를 작성하십시오.

    sorted(set([c for c in chars]))
  3. 각 문자의 발생 횟수를 세고 인쇄하십시오.

    print(c+" -", chars.count(c)) for c in <uniques>

사용하는 방법

  1. 빈 파일에 코드를 붙여넣고 다른 이름으로 저장하십시오. chars_count.py
  2. 다음 중 하나를 수행하여 파일을 인수로 실행하십시오.

    /path/to/chars_count.py </path/to/file>

    스크립트가 실행 가능한 경우 또는

    python3 /path/to/chars_count.py </path/to/file>

    그렇지 않다면


5

기본적으로 F는 의 ield S의 eparator (FS) 인 공간 또는 . 각 문자를 세고 싶기 때문에 FS를 none ( FS="") 으로 다시 정의하여 각 문자를 별도의 줄로 나누고 배열에 저장하고 END{..}블록 내부의 끝 에서 다음 명령으로 총 발생 횟수를 인쇄해야합니다 .

$ awk '{for (i=1;i<=NF;i++) a[$i]++} END{for (c in a) print c,a[c]}' FS="" file
A 1
M 1
O 1
T 1
a 4
c 1
k 1
n 1
o 4
s 2
t 3
w 2
y 1

에서 {for (i=1;i<=NF;i++) a[$i]++} ... FS="" ...블록 우리는 단지 문자를 분할합니다. 그리고
END{for (c in a) print c,a[c]}블록 우리는 배열에 반복되어 a그 안에 문자를 저장 인쇄가 print c와 발생의 수a[c]


3

for계산하려는 모든 문자에 대해 루프를 수행 grep -io하고 문자 및 대소 문자를 무시하고 wc -l인스턴스를 계산하고 결과를 인쇄하는 데 사용하십시오.

이처럼 :

#!/bin/bash

filename="1.txt"

for char in {a..z}
do
    echo "${char} - `grep -io "${char}" ${filename} | wc -l`,"
done

스크립트는 이것을 출력합니다 :

a - 5,
b - 0,
c - 1,
d - 0,
e - 0,
f - 0,
g - 0,
h - 0,
i - 0,
j - 0,
k - 1,
l - 0,
m - 1,
n - 1,
o - 5,
p - 0,
q - 0,
r - 0,
s - 2,
t - 4,
u - 0,
v - 0,
w - 2,
x - 0,
y - 1,
z - 0,

댓글 후 수정

인쇄 가능한 모든 문자에 대해 루프를 만들려면 다음을 수행하십시오.

#!/bin/bash

filename="a.txt"

for num in {32..126}
do
   char=`printf "\x$(printf %x ${num})"`
   echo "${char} - `grep -Fo "${char}" ${filename} | wc -l`,"
done

32에서 126까지의 모든 ANSI 문자를 계산합니다. 가장 일반적으로 읽을 수있는 문자입니다. 이것은 대소 문자를 무시하지 않습니다.

이것의 결과는 다음과 같습니다.

- 0,
! - 0,
" - 0,
# - 0,
$ - 0,
% - 0,
& - 0,
' - 0,
( - 0,
) - 0,
* - 0,
+ - 0,
, - 0,
- - 0,
. - 0,
/ - 0,
0 - 0,
1 - 0,
2 - 0,
3 - 0,
4 - 0,
5 - 0,
6 - 0,
7 - 0,
8 - 0,
9 - 0,
: - 0,
; - 0,
< - 0,
= - 0,
> - 0,
? - 0,
@ - 0,
A - 1,
B - 0,
C - 0,
D - 0,
E - 0,
F - 0,
G - 0,
H - 0,
I - 0,
J - 0,
K - 0,
L - 0,
M - 1,
N - 0,
O - 1,
P - 0,
Q - 0,
R - 0,
S - 0,
T - 1,
U - 0,
V - 0,
W - 0,
X - 0,
Y - 0,
Z - 0,
[ - 0,
\ - 0,
] - 0,
^ - 0,
_ - 0,
` - 0,
a - 4,
b - 0,
c - 1,
d - 0,
e - 0,
f - 0,
g - 0,
h - 0,
i - 0,
j - 0,
k - 1,
l - 0,
m - 0,
n - 1,
o - 4,
p - 0,
q - 0,
r - 0,
s - 2,
t - 3,
u - 0,
v - 0,
w - 2,
x - 0,
y - 1,
z - 0,
{ - 0,
| - 0,
} - 0,
~ - 0,

대소 문자를 무시하지 않으려면 igrep에서 를 제거하십시오 . (질문에서 당신은 예상 결과에서 3을 얻었습니다)
stalet

오 감사. "{a..z}"- 'a'에서 'z'까지의 모든 기호입니까? 인쇄 할 수있는 모든 기호는 무엇입니까? 모두 나열하지 않고 지정할 수있는 방법
Set-xx

필자는 읽을 수있는 모든 문자에 대한 검색을 확장하는 방법에 대한 예제로 대답을 업데이트했습니다.
stalet

그것은 전체 입력을 반복해서 많이 호출합니다 grep.
200_success

3

여기 또 다른 해결책 (awk) ...

awk '
        { for (indx=length($0); indx >= 1; --indx)
                ++chars[tolower(substr($0, indx, 1))]
        }
END     { for (c in chars) print c, chars[c]; }
' 1.txt | sort
  • 각 문자를 색인 값으로, 개수를 배열 값으로 사용하여 연관 배열을 작성합니다.
  • END 액션은 배열을 인쇄합니다.

필요 없음 cat file | awk '...': 직접 말할 수 있습니다 awk '...' file.
fedorqui

2

다음 perloneliner가 계산을 수행합니다. 정규식을 목록 컨텍스트에 넣고 (일치 수를 얻기 위해) 스칼라 컨텍스트에 넣습니다.

$ perl -e '$a=join("",<>);for("a".."z"){$d=()=$a=~/$_/gi;print"$_ - $d,\n"}' 1.txt
a - 5,
b - 0,
c - 1,
d - 0,
e - 0,
f - 0,
g - 0,
h - 0,
i - 0,
j - 0,
k - 1,
l - 0,
m - 1,
n - 1,
o - 5,
p - 0,
q - 0,
r - 0,
s - 2,
t - 4,
u - 0,
v - 0,
w - 2,
x - 0,
y - 1,
z - 0,

후행 쉼표를 제거하려면 상당한 재 작성이 필요한 것 같습니다.perl -Mfeature=say -e '$a=join("",<>);say join(",\n", map { sprintf("%s - %d", $_, ($d=()=$a=~/$_/gi)); } ("a".."z"))'
200_success

2

다음은 Python을 사용하는 솔루션입니다.

#!/usr/bin/env python2
import collections, string
with open('1.txt') as f:
    input_string = f.read().replace('\n', '').lower()
    count_dict = collections.Counter(input_string)
    for char in string.lowercase:
        print char + ' - ' + str(count_dict[char]) + ','

여기서 우리는 collections모듈의 Counter클래스를 사용하여 각 문자의 발생 횟수를 계산 한 다음 인쇄 목적으로 string모듈을 사용 하여 변수로 모든 소문자를 가져 왔습니다 string.lowercase.

예를 들어 위의 스크립트를 원하는 이름으로 파일에 저장하십시오 count.py. 이제 파일이 저장된 동일한 디렉토리에서 파일을 실행 python count.py하기 위해 간단히 실행할 수 있으며 , 다른 디렉토리에서 파일의 절대 경로를 사용하여 파일을 실행할 수 python /absolute/path/to/count.py있습니다.


솔루션을 명확하게 설명해 주시겠습니까? 내 말은 : file_name 파일을
만들고이

@ c0rp : done ....
heemayl

1

얼마 전에 저는 파일 을보고 약간의 스태틱을 생성 해야했기 때문에 C 프로그램을 작성했습니다 .

#include <stdlib.h>
#include <stdint.h>
#include <stdio.h>
#include <ctype.h>
#include <limits.h>
#include <math.h>
#include <sysexits.h>


inline static double square(double x)
{
    return x * x;
}


int main()
{
    static const unsigned distribution_size = 1 << CHAR_BIT;

    int rv = EX_OK;
    uintmax_t *distribution = calloc(distribution_size, sizeof(*distribution));

    {
        int c;
        while ((c = getchar()) != EOF)
            distribution[c]++;

        if (ferror(stdin)) {
            perror("I/O error on standard input");
            rv = EX_IOERR;
        }
    }

    uintmax_t sum = 0;
    for (unsigned i = 0; i != distribution_size; i++)
        sum += distribution[i];
    double avg = (double) sum / distribution_size;

    double var_accum = 0.0;
    for (unsigned i = 0; i != distribution_size; i++)
    {
        const uintmax_t x = distribution[i];

        printf("'%c' (%02X): %20ju", isprint((int) i) ? i : ' ', i, x);
        if (x != 0) {
            var_accum += square((double) x - avg);
            printf(" (%+.2e %%)\n", ((double) x / avg - 1.0) * 100.0);
        } else {
            var_accum += square(avg);
            putchar('\n');
        }
    }

    double stdev = sqrt(var_accum / distribution_size);
    double varcoeff = stdev / avg;
    printf(
        "total: %ju\n"
        "average: %e\n"
        "standard deviation: %e\n"
        "variation coefficient: %e\n",
        sum, avg, stdev, varcoeff);

    free(distribution);
    return rv;
}

로 컴파일 (소스 코드가 있다고 가정 character-distribution.c) :

cc -std=c99 -O2 -g0 -o character-distribution character-distribution.c

로 실행 :

./character-distribution < 1.txt

C 컴파일러가 준비되어 있지 않으면 GCC를 설치하십시오.

sudo apt-get install gcc build-essential

0

Python 2.7 및 Python 3에서 작동하는 더 엄격한 코드를 사용하여 @heemayl과 비슷한 솔루션입니다.

#!/usr/bin/python

import collections
import fileinput
import itertools
import string

count = collections.Counter(itertools.chain(*fileinput.input()))
print(',\n'.join('{} - {}'.format(c, count[c] + count[c.upper()])
                 for c in string.ascii_lowercase))

첫 번째 진술 count = collections.Counter(…)은 모든 실제 작업을 수행합니다.

  • fileinput.input() stdin을 통해 또는 명령 행 인수로 파이프 될 수있는 입력의 모든 행을 읽습니다.
  • * 한 번에 한 줄이 아닌 한 번에 한 문자를 고려합니다.
  • count = Counter(…)단일 패스에서 각 문자의 발생을 효율적으로 계산하고 결과를 count변수 에 저장합니다 .

두 번째 줄은 결과를 인쇄합니다.

  • '{} - {}'.format(c, count[c] + count[c.upper()]) for c in string.ascii_lowercase 각 캐릭터와 그 수의 목록을 만듭니다.
  • print(',\n'.join(…)) 원하는 형식으로 입력합니다 : 한 줄에 하나씩, 쉼표로 구분되지만 마지막 줄에는 쉼표가 없습니다.

0

GNU awk 4.1

awk -iwalkarray '{for (;NF;NF--) b[$NF]++} END {walk_array(b)}' FS=
[A] = 1
[O] = 1
[w] = 2
[k] = 1
[y] = 1
[T] = 1
[n] = 1
[a] = 4
[o] = 4
[c] = 1
[s] = 2
[t] = 3
[M] = 1

GNU awk의 이전 버전이 있다면를 사용할 수 있습니다 for (c in b) print c, b[c].


0

루비를 사용한 답은 다음과 같습니다. 문자열을 다른 문자의 uniq 목록으로 변경하고 각 문자에 대해 count 메소드를 사용하여 수행됩니다.

#!/usr/bin/env ruby

String content = IO.read("1.txt")
content.split("").uniq.sort.each { |chr| puts( chr + ' - ' + content.count(chr).to_s) }
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.