Как считать случаи каждого символа?

Например, у меня есть файл 1.txt, это содержит:

Moscow
Astana
Tokyo
Ottawa

Я хочу считать количество всего символа как:

a - 4,
b - 0,
c - 1,
...
z - 0
13
задан 6 March 2015 в 15:13

11 ответов

Вы могли использовать это:

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 может быть опущен, если Вы не хотите нечувствительности к регистру.

20
ответ дан 23 November 2019 в 03:10

По умолчанию в (FS) F ield S eparator пространство или вкладка . Так как мы хотим считать каждый символ, мы должны будем переопределить FS ни к чему (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]

5
ответ дан 23 November 2019 в 03:10

Сделайте 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

Это будет считать все символы ANSI от 32 до 126 - это обычно читаемые. Обратите внимание, что это не использует, игнорируют регистр.

вывод от этого будет:

- 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,
3
ответ дан 23 November 2019 в 03:10

Вот решение с помощью 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.

2
ответ дан 23 November 2019 в 03:10

Только что я записал программу 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
1
ответ дан 23 November 2019 в 03:10

Аналогичное решение @heemayl, с более трудным кодом, который работает над Python 2.7 и Python 3.

#!/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
ответ дан 23 November 2019 в 03:10

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
ответ дан 23 November 2019 в 03:10

Вот ответ с помощью рубина. Это сделано, меняя струну в uniq список различных символов и используя метод счета для каждого из них.

#!/usr/bin/env ruby

String content = IO.read("1.txt")
content.split("").uniq.sort.each { |chr| puts( chr + ' - ' + content.count(chr).to_s) }
0
ответ дан 23 November 2019 в 03:10

Здесь другое решение (в 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
  • Это создает ассоциативный массив с каждым символом как индексное значение и количество как значение массива.
  • Действие КОНЦА печатает массив.
3
ответ дан 23 November 2019 в 03:10

Следующее perl острота проведет подсчет. Я поместил regex в контекст списка (чтобы получить количество соответствий) и поместить это в скалярный контекст:

$ 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,
2
ответ дан 23 November 2019 в 03:10

Немного поздно, но завершать набор, другой 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. Создайте (отсортированный) набор uniques:

    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>
    

    если это не

6
ответ дан 23 November 2019 в 03:10

Другие вопросы по тегам:

Похожие вопросы: