Misalnya saya punya file 1.txt
, yang berisi:
Moscow
Astana
Tokyo
Ottawa
Saya ingin menghitung jumlah semua char sebagai:
a - 4,
b - 0,
c - 1,
...
z - 0
Misalnya saya punya file 1.txt
, yang berisi:
Moscow
Astana
Tokyo
Ottawa
Saya ingin menghitung jumlah semua char sebagai:
a - 4,
b - 0,
c - 1,
...
z - 0
Jawaban:
Anda bisa menggunakan ini:
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
Bagian ini sed
menempatkan baris baru setelah setiap karakter. Kemudian kami sort
ouput secara alfabet. Dan pada akhirnya uniq
menghitung jumlah kejadian. The -i
Bendera uniq
dapat menghilangkan sebagian jika Anda tidak ingin kasus ketidakpekaan.
sort -k 2
daftar mereka berdasarkan alfanumerik.
sed -e $'s/\(.\)/\\1\\\n/g'
(lihat juga stackoverflow.com/a/18410122/179014 )
| sort -rnk 1
. Dan jika Anda berurusan dengan file yang sangat besar, seperti saya, Anda bisa mencicipi beberapa ribu baris untuk mendapatkan proksi untuk hitungan aktual:cat 1.txt | shuf -n 10000 | sed 's/\(.\)/\1\n/g' | sort | uniq -ic | sort -rnk 1
Agak terlambat, tetapi untuk menyelesaikan set, pendekatan python lain (3), hasil diurutkan:
#!/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
Baca file, lewati spasi dan kembali sebagai "karakter":
chars = open(sys.argv[1]).read().strip().replace("\n", "")
Buat seperangkat unik (diurutkan):
sorted(set([c for c in chars]))
Hitung dan cetak kemunculan untuk masing-masing karakter:
print(c+" -", chars.count(c)) for c in <uniques>
chars_count.py
Jalankan dengan file sebagai argumen oleh:
/path/to/chars_count.py </path/to/file>
jika skrip dapat dieksekusi, atau:
python3 /path/to/chars_count.py </path/to/file>
jika tidak
Secara default di awk , F ield S eparator (FS) adalah spasi atau tab . Karena kami ingin menghitung setiap karakter, kami harus mendefinisikan ulang FS menjadi nothing ( FS=""
) untuk membagi setiap karakter dalam baris yang terpisah dan menyimpannya ke dalam array dan pada akhirnya di dalam END{..}
blok, cetak total kemunculannya dengan perintah awk berikut :
$ 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
Dalam {for (i=1;i<=NF;i++) a[$i]++} ... FS="" ...
blok kami hanya membagi karakter. Dan
dalam END{for (c in a) print c,a[c]}
blok kita mengulang ke array a
dan mencetak karakter yang disimpan di dalamnya print c
dan jumlah kemunculannyaa[c]
Lakukan for
perulangan untuk semua karakter yang ingin Anda hitung, dan gunakan grep -io
untuk mendapatkan semua kemunculan karakter dan abaikan case, dan wc -l
untuk menghitung instance, dan cetak hasilnya.
Seperti ini:
#!/bin/bash
filename="1.txt"
for char in {a..z}
do
echo "${char} - `grep -io "${char}" ${filename} | wc -l`,"
done
Script menghasilkan ini:
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,
Sunting setelah komentar
Untuk membuat lingkaran untuk semua karakter yang dapat dicetak, Anda dapat melakukan ini:
#!/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
Ini akan menghitung semua karakter ANSI dari 32 hingga 126 - ini adalah yang paling umum dibaca. Perhatikan bahwa ini tidak menggunakan kasus abaikan.
output dari ini adalah:
- 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,
i
dari grep. (dalam pertanyaan Anda, Anda hanya memiliki 3 dalam hasil yang diharapkan)
grep
seluruh input berulang kali.
Di sini solusi lain (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
cat file | awk '...'
: bisa langsung di bilang awk '...' file
.
perl
Oneliner berikut akan menghitung. Saya menempatkan regex dalam konteks daftar (untuk mendapatkan jumlah kecocokan) dan memasukkannya ke dalam konteks skalar:
$ 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"))'
Berikut ini solusi menggunakan 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]) + ','
Di sini kita telah menggunakan kelas collections
modul Counter
untuk menghitung jumlah kemunculan setiap karakter, kemudian untuk tujuan pencetakan kita telah menggunakan string
modul untuk mendapatkan semua huruf kecil dengan variabel string.lowercase
.
Simpan skrip di atas dalam file yang memberikan nama apa pun yang Anda inginkan misalnya count.py
. Sekarang dari direktori yang sama di mana file disimpan, Anda dapat menjalankan python count.py
untuk menjalankan file, dari direktori lain menggunakan jalur absolut ke file untuk menjalankannya yaitu python /absolute/path/to/count.py
.
Beberapa waktu yang lalu saya menulis program C untuk melakukan itu, karena saya membutuhkannya untuk melihat file besar dan menghasilkan beberapa statika.
#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;
}
kompilasi dengan (dengan asumsi kode sumber berada di character-distribution.c
):
cc -std=c99 -O2 -g0 -o character-distribution character-distribution.c
jalankan dengan:
./character-distribution < 1.txt
Jika Anda tidak memiliki kompiler C yang siap, instal GCC:
sudo apt-get install gcc build-essential
Solusi serupa dengan @heemayl, dengan kode yang lebih ketat, yang berfungsi pada Python 2.7 dan 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))
Pernyataan pertama, count = collections.Counter(…)
melakukan semua pekerjaan nyata.
fileinput.input()
membaca setiap baris input, yang dapat disalurkan melalui stdin atau sebagai argumen baris perintah.*
membuatnya mempertimbangkan karakter pada suatu waktu daripada garis pada suatu waktu.count = Counter(…)
menghitung kemunculan setiap karakter secara efisien, dalam sekali lintasan, dan menyimpan hasilnya dalam count
variabel.Baris kedua hanya mencetak hasilnya.
'{} - {}'.format(c, count[c] + count[c.upper()]) for c in string.ascii_lowercase
membuat daftar setiap karakter dan jumlahnya.print(',\n'.join(…))
menempatkannya dalam format yang diinginkan: satu per baris, dipisahkan dengan koma, tetapi tidak ada koma di baris terakhir.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
Jika Anda memiliki versi GNU awk yang lebih lama, Anda dapat menggunakannya for (c in b) print c, b[c]
.
Inilah jawabannya menggunakan ruby. Hal ini dilakukan dengan mengubah string menjadi daftar unik karakter yang berbeda dan menggunakan metode hitungan pada masing-masing karakter.
#!/usr/bin/env ruby
String content = IO.read("1.txt")
content.split("").uniq.sort.each { |chr| puts( chr + ' - ' + content.count(chr).to_s) }