Na przykład mam plik 1.txt
, który zawiera:
Moscow
Astana
Tokyo
Ottawa
Chcę policzyć liczbę wszystkich znaków jako:
a - 4,
b - 0,
c - 1,
...
z - 0
command-line
bash
text-processing
Set-xx
źródło
źródło
Odpowiedzi:
Możesz użyć tego:
Ta
sed
część umieszcza nowy wiersz po każdej postaci. Następniesort
wypowiadamy się alfabetycznie. I w końcuuniq
liczy się liczba wystąpień.-i
Flagauniq
może być, pominięte, jeśli nie chcesz case niewrażliwość.źródło
sort -k 2
aby wyświetlić je alfanumerycznie.sed -e $'s/\(.\)/\\1\\\n/g'
(patrz także stackoverflow.com/a/18410122/179014 )| sort -rnk 1
. A jeśli masz do czynienia z bardzo dużymi plikami, tak jak ja, możesz po prostucat 1.txt | shuf -n 10000 | sed 's/\(.\)/\1\n/g' | sort | uniq -ic | sort -rnk 1
Trochę późno, ale aby ukończyć zestaw, inne podejście do Pythona (3) posortowało wynik:
Wyjaśnienie
Przeczytaj plik, pomiń spacje i zwraca jako „znaki”:
Utwórz (posortowany) zestaw unikatów:
Policz i wydrukuj wystąpienie każdego z znaków:
Jak używać
chars_count.py
Uruchom go z plikiem jako argumentem:
jeśli skrypt jest wykonywalny lub:
jeśli nie jest
źródło
Domyślnie awk F ield S eparator (FS), znajduje się przestrzeń lub karta . Ponieważ chcemy policzyć każdy znak, będziemy musieli ponownie zdefiniować FS na nic (
FS=""
), aby podzielić każdy znak na osobną linię i zapisać go w tablicy, a na końcuEND{..}
bloku wewnętrznego wydrukować ich całkowitą liczbę wystąpień za pomocą następującego polecenia awk :W
{for (i=1;i<=NF;i++) a[$i]++} ... FS="" ...
bloku po prostu dzielimy znaki. Aw
END{for (c in a) print c,a[c]}
bloku zapętlamy się do tablicya
i wypisujemy w niej zapisany znakprint c
i jego liczbę wystąpieńa[c]
źródło
Wykonaj
for
pętlę dla wszystkich znaków, które chcesz policzyć, i użyj,grep -io
aby uzyskać wszystkie wystąpienia postaci i ignorowanie wielkości liter orazwc -l
zliczyć wystąpienia i wydrukować wynik.Lubię to:
Skrypt generuje to:
EDYTUJ po komentarzu
Aby utworzyć pętlę dla wszystkich drukowalnych znaków, możesz to zrobić:
Policzy to wszystkie znaki ANSI od 32 do 126 - są to najczęściej czytane. Pamiętaj, że nie używa to ignorowania wielkości liter.
wyjście z tego będzie:
źródło
i
grep. (w swoim pytaniu miałeś tylko 3 oczekiwany wynik)grep
całego wejścia wielokrotnie.Oto inne rozwiązanie (w awk) ...
źródło
cat file | awk '...'
: możesz bezpośrednio powiedziećawk '...' file
.perl
Liczy się następujący oneliner. Umieszczam wyrażenie regularne w kontekście listy (aby uzyskać liczbę dopasowań) i umieszczam je w kontekście skalarnym:źródło
perl -Mfeature=say -e '$a=join("",<>);say join(",\n", map { sprintf("%s - %d", $_, ($d=()=$a=~/$_/gi)); } ("a".."z"))'
Oto rozwiązanie wykorzystujące Python:
W tym przypadku wykorzystaliśmy klasę
collections
modułuCounter
do zliczenia liczby wystąpień każdego znaku, a następnie do celów drukowania użyliśmystring
modułu, aby uzyskać wszystkie małe litery według zmiennejstring.lowercase
.Zapisz powyższy skrypt w pliku, nadając mu dowolną nazwę, np
count.py
. Teraz z tego samego katalogu, w którym zapisany jest plik, możesz po prostu uruchomić go,python count.py
aby wykonać plik, z dowolnego innego katalogu użyj bezwzględnej ścieżki do pliku, aby go wykonać, tjpython /absolute/path/to/count.py
.źródło
Jakiś czas temu napisałem program C, aby to zrobić, ponieważ potrzebowałem go do przeglądania dużych plików i tworzenia statystyk.
skompiluj z (zakładając, że kod źródłowy znajduje się w
character-distribution.c
):Biegnij z:
Jeśli nie masz gotowego kompilatora C, zainstaluj GCC:
źródło
Podobne rozwiązanie do @heemayl, z bardziej ścisłym kodem, który działa w Python 2.7 i Python 3.
Pierwsze stwierdzenie
count = collections.Counter(…)
wykonuje całą prawdziwą pracę.fileinput.input()
czyta każdy wiersz danych wejściowych, które mogą być przesyłane potokowo przez stdin lub jako argumenty wiersza poleceń.*
sprawia, że rozważa się postać zamiast naraz.count = Counter(…)
skutecznie liczy wystąpienia każdej postaci w jednym przejściu i zapisuje wynik wcount
zmiennej.Druga linia po prostu drukuje wyniki.
'{} - {}'.format(c, count[c] + count[c.upper()]) for c in string.ascii_lowercase
tworzy listę każdego znaku i jego liczbę.print(',\n'.join(…))
umieszcza go w żądanym formacie: jeden w wierszu, oddzielony przecinkami, ale nie ma przecinka w ostatnim wierszu.źródło
GNU awk 4.1
Jeśli masz wcześniejszą wersję GNU awk, możesz jej użyć
for (c in b) print c, b[c]
.źródło
Oto odpowiedź przy użyciu ruby. Odbywa się to poprzez zamianę ciągu na unikalną listę różnych znaków i użycie metody count na każdym z nich.
źródło