Tente isto:
<file.txt sed 's/^\(.\).*//' | sort | uniq -c
Ou, se você quiser insensível a maiúsculas, isso:
<file.txt sed 's/^\(.\).*//' | tr a-z A-Z | sort | uniq -c
Eu tenho um arquivo com várias linhas em um nome de arquivo.
Eu quero contar quantas linhas começam com o caractere 'a', com 'b' e assim por diante de uma só vez.
Qual comando devo executar?
Para letras de caracteres simples:
< file cut -c1 | grep '[[:alpha:]]' | LC_ALL=C sort | LC_ALL=C uniq -c | sort -k 2
Para lidar com caracteres combinados, se estiver em uma localidade utf-8:
< file PERLIO=:utf8 perl -Mlocale -MUnicode::Normalize -lne '
$_=NFKD($_); $n{$&}++ if /^[[:alpha:]]/u && /^\X/u;
END{for $i (sort keys %n) {print "$n{$i} $i"}}'
(substitua $n{$&}
por $n{lc$&}
para contagem independente de caso).
Em uma entrada como:
fix
été
-dash-
éléphant
παράλληλα
молчит
alphabet
3com
foo
ɪ-letter
ʃ-letter
Na minha localidade, o primeiro resultado seria:
1 ɪ
1 ʃ
1 a
1 e
1 é
2 f
1 π
1 м
Porque éléphant acima (que, a propósito, minha versão do firefox é exibida incorretamente, pois coloca o acento no l
), o primeiro é
é escrito como os dois caracteres unicode e
e \U0301
(combinando acento agudo), enquanto em été
, é o \U00E9
pré-composto e
com acento agudo.
E o segundo seria exibido:
1 ɪ
1 ʃ
1 a
2 é
2 f
1 π
1 м
(lá, todas as variantes de é
foram convertidas para e\U0301
(a versão decomposta normalizada)).
Enquanto cut -c 1 | grep '[[:alpha:]]' | sort | uniq -c
produziria:
2 ɪ
1 a
1 e
1 é
2 f
1 π
1 м
porque na minha localidade, a ordem de classificação de ɪ
e ʃ
não está definida, então eles ordenam o mesmo e contam como o mesmo que sort
e uniq
.
(note que você precisa de um POSIX cut
acima. Minha versão do GNU cut
não é como trata caracteres como bytes, então eu tive que usar o cut
construído em ksh93
para isso). / p>
Se os dados forem apenas US-ASCII, você poderá simplificá-lo para:
(export LC_ALL=C; < file cut -c 1 | grep '[[:alpha:]]' | sort | uniq -c)
Ou se você quiser denunciar 0
para qualquer uma das 52 letras ASCII dos EUA que não foram encontradas:
< file LC_ALL=C awk '{n[substr($0,1,1)]++};END{
for(i=65;i<=122;i++) if (i < 91 || i > 96) {
c=sprintf("%c",i);print 0+n[c], c}}'