jak policzyć całkowitą liczbę słów w pliku?

18

Szukam polecenia zliczającego liczbę wszystkich słów w pliku. Na przykład jeśli plik jest taki,

today is a 
good day

to powinno się wydrukować 5, ponieważ są 5tam słowa.

Richard
źródło
7
Próbowałeś wc -w $FILE?
don_crissti,

Odpowiedzi:

39

Polecenie wcaka. liczba słów może to zrobić:

$ wc -w <file>

przykład

$ cat sample.txt
today is a 
good day


$ wc -w sample.txt
5 sample.txt


# just the number (thanks to Stephane Chazelas' comment)
$ wc -w < sample.txt
5
slm
źródło
1
Zauważ, że słowa dla wc -wnie mają takiej samej definicji jak dla GNU grep -w. Dla wcsłowa jest sekwencją jednego lub więcej znaków niż kosmiczne ( [:space:]klasa znaków w bieżącej lokalizacji). Na przykład, foo,bari foo bar(o nierozdzielającą przestrzeni) każdy jeden wyraz.
Stéphane Chazelas
7

Wymyśliłem to po prostu numer:

wc -w [file] | cut -d' ' -f1

5

Podoba mi się również wc -w < [file]podejście

Wreszcie, do przechowywania tylko liczby słów w zmiennej, możesz użyć:

myVar=($(wc -w /path/to/file))

Pozwala to elegancko pominąć nazwę pliku.

Michael Durrant
źródło
14
wc -w < "$file"po prostu numer.
Stéphane Chazelas,
3

Lepszym rozwiązaniem jest użycie Perla:

perl -nle '$word += scalar(split(/\s+/, $_)); END{print $word}' filename

@Bernhard

Możesz sprawdzić kod źródłowy wcpolecenia z coreutils, testuję na moim komputerze, z plikiem subst.cw źródle bash 4.2.

time wc -w subst.c

real    0m0.025s
user    0m0.016s
sys     0m0.000s

I

time perl -nle '$word += scalar(split(" ", $_)); END{print $word}' subst.c

real    0m0.021s
user    0m0.016s
sys     0m0.004s

Im większy plik, tym bardziej wydajny jest Perl w stosunku do wc.

Cuonglm
źródło
13
Dlaczego to jest lepsze niż wc?
Sparr
2
@Sparr z jednej strony, ponieważ, ku mojemu wielkiemu zaskoczeniu, wydaje się, że jest znacznie szybszy. Próbowałem na pliku tekstowym zawierającym 141813504 słów i wczabrało ~ 14 sekund, podczas gdy Perl zajął ~ 5 sekund!
terdon
3
Myślę, że „większy” problem naprawdę jest odpowiedzią zależną od Perla i nigdy nie jestem wielkim fanem takiej zależności. Gdyby pytanie dotyczyło wydajności, byłaby to inna sprawa.
Michael Durrant,
5
Zauważ, że na to jak z tym że każdy czołowy spacje produkuje null pierwsze pole. Ta różnica da ci jedno dodatkowe słowo (tzn. Pierwsze pole zerowe) na link linii . Więc użyj inaczej dla pliku utworzonego w ten sposób: twój linijka zgłasza 3 słowa. split/\s+/split(' ') (split(" ", $_))echo -e "unix\n linux" > testfile
don_crissti
1
Twoje czasy pokazują, że wc jest szybsze (liczą się tam czasy użytkownika i sys). Z LC_ALL = C wcbędzie znacznie szybszy, podobnie jak z PERLIO=:utf8, perlbędzie znacznie wolniejszy.
Stéphane Chazelas
3

Użyjmy AWK!

$ function wordfrequency() { awk 'BEGIN { FS="[^a-zA-Z]+" } { for (i=1; i<=NF; i++) { word = tolower($i) words[word]++ } } END { for (w in words) printf("%3d %s\n", words[w], w) } ' | sort -rn } 
$ cat your_file.txt | wordfrequency

Podaje częstotliwość każdego słowa występującego w dostarczonym pliku. Wiem, że nie o to prosiłeś, ale lepiej! Jeśli chcesz zobaczyć wystąpienia swojego słowa, możesz po prostu to zrobić:

$ cat your_file.txt | wordfrequency | grep yourword

Dodałem nawet tę funkcję do moich plików .dotfiles


Źródło: AWK-ward Ruby

Sheharyar
źródło
Liczy słowa, więc jest dla mnie wystarczająco dobry! :-)
aggsol
3

W wcprogramie liczy „Słowa”, ale nie są to na przykład „słowa”, że wiele osób będzie zobaczyć, kiedy zbadać plik. Na viprzykład program używa innej miary „słów”, ograniczając je w oparciu o ich klasy znaków, a wcpo prostu liczy rzeczy oddzielone spacjami . Te dwa środki mogą się radykalnie różnić. Rozważ ten przykład:

first,second

viwidzi trzy słowa ( pierwszy i drugi oraz przecinek oddzielający je), a wcwidzi jedno (w tym wierszu nie ma białych znaków). Istnieje wiele sposobów liczenia słów, niektóre są mniej przydatne niż inne.

Chociaż Perl byłyby lepiej przystosowane do pisania licznik za słowa vi stylu, oto krótki przykład przy użyciu sed, tri wc(umiarkowanie przenośny za pomocą dosłownych powrotu karetki ^M):

#!/bin/sh
in_words="[[:alnum:]_]"
in_punct="[][{}\\|:\"';<>,./?\`~!@#$%^&*()+=-]"
sed     -e "s/\($in_words\)\($in_punct\)/\1^M\2/g" \
        -e "s/\($in_punct\)\($in_words\)/\1^M\2/g" \
        -e "s/[[:space:]]/^M/g" \
        "$@" |
tr '\r' '\n' |
sed     -e '/^$/d' |
wc      -l

Porównywanie liczby:

  • Uruchomienie samego skryptu daje mi 76 słów.
  • Przykład w Perlu autorstwa @cuonglm podaje 31.
  • Używanie wcdaje 28.

W celach informacyjnych POSIX vi mówi:

W ustawieniach regionalnych POSIX, vi rozpoznaje pięć rodzajów słów:

  1. Maksymalna sekwencja liter, cyfr i znaków podkreślenia na obu końcach:

    • Znaki inne niż litery, cyfry lub podkreślenia

    • Początek lub koniec linii

    • Początek lub koniec bufora edycji

  2. Maksymalna sekwencja znaków innych niż litery, cyfry, podkreślenia lub znaki, ograniczone na obu końcach przez:

    • Litera, cyfra, podkreślenie
    • <blank> postacie
    • Początek lub koniec linii
    • Początek lub koniec bufora edycji
  3. Jedna lub więcej kolejnych pustych linii

  4. Pierwszy znak w buforze edycji

  5. Ostatni nie <newline>w buforze edycji

Thomas Dickey
źródło