як підрахувати загальну кількість слів у файлі?


18

Шукаю команду для підрахунку кількості всіх слів у файлі. Наприклад, якщо такий файл,

today is a 
good day

тоді він повинен надрукувати 5, оскільки там є 5слова.


7
Ви пробували wc -w $FILE?
don_crissti

Відповіді:


39

Команда wcака. кількість слів може це зробити:

$ wc -w <file>

приклад

$ 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

1
Зауважте, що слова for wc -wне мають того самого визначення, що і для GNU grep -w. Для wcслова - це послідовність одного або декількох символів, що не містять пробілів ( [:space:]клас символів у поточній мові). Наприклад, foo,barі foo bar(з пробілом) - це одне слово.
Стефан Шазелас

7

Я придумав це ДІЙКІСТЬ номер:

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

5

Мені також подобається wc -w < [file]підхід

Нарешті, для зберігання лише кількості слів у змінній ви можете використовувати наступне:

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

Це дозволяє елегантно пропустити ім'я файлу.


14
wc -w < "$file"ЗА ПОВЕРНЕНО число.
Стефан Шазелас

3

Краще рішення - використання Perl:

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

@Bernhard

Ви можете перевірити вихідний код wcкоманди з coreutils, який я перевіряю на своїй машині, з файлом subst.cу джерелі bash 4.2.

time wc -w subst.c

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

І

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

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

Чим більший файл, тим ефективніше Perl щодо wc.


13
Чому це краще, ніж туалет?
Спарр

2
@Sparr для одного, тому що, на мій надзвичайний подив, це здається набагато швидшим. Я спробував це в текстовому файлі з 141813504 словами і wcвзяв ~ 14 сек, тоді як Perl взяв ~ 5 сек!
terdon

3
Я думаю, що "більший" питання насправді - це відповідь, яка залежить від Perl, і я ніколи не є великим прихильником такої залежності. Якби питання стосувалося виступу, це було б іншою справою.
Майкл Дюррант

5
Зауважте, що a splitна /\s+/- це як split(' ')виняток, що будь-який провідний пробіл виробляє нульове перше поле. Ця різниця дасть вам одне додаткове слово (нульове перше поле, тобто) за кожне посилання . Тож використовуйте (split(" ", $_))інакше для файлу, створеного таким чином: echo -e "unix\n linux" > testfileваш однокласник повідомляє 3 слова.
don_crissti

1
Ваші таймінги показують, що wc швидше (це користувач і систематизує важливі для цього рази). З LC_ALL = C, wcбуде значно швидше, як і з PERLIO=:utf8, perlбуде значно повільніше.
Стефан Шазелас

3

Давайте скористаємося 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

Тут перерахована частота кожного слова, що зустрічається у наданому файлі. Я знаю, що це не те, про що ви просили, але краще! Якщо ви хочете побачити слова вашого слова, ви можете просто зробити це:

$ cat your_file.txt | wordfrequency | grep yourword

Я навіть додав цю функцію до своїх .dotfiles


Джерело: AWK-палатка Ruby


Він рахує слова, тож мені це досить добре! :-)
aggsol

3

У wcпрограмі підраховує «слова», але такими не є, наприклад , «слова» , що багато людей бачать , коли вони розглядають файл. Наприклад, viпрограма використовує іншу міру "слів", розмежовуючи їх на основі класів символів, при цьому wcпросто рахує речі, розділені пробілом . Два заходи можуть бути кардинально різними. Розглянемо цей приклад:

first,second

viбачить три слова ( перше і друге , а також кома, що розділяє їх), а wcбачить одне (у цьому рядку немає пробілу). Існує багато способів підрахунку слів, деякі з них менш корисні, ніж інші.

У той час як Perl буде краще підходить для написання лічильник для слів ві-стилю, ось швидкий приклад використання sed, trі wc(помірно портативний , використовуючи літерні символи повернення каретки ^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

Порівняння підрахунків:

  • Запуск сценарію на себе дає мені 76 слів.
  • Приклад в Perl від @cuonglm дає 31.
  • Використання wcдає 28.

Для довідки, POSIX vi каже:

У локалі POSIX vi повинен розпізнавати п'ять видів слів:

  1. Максимальна послідовність букв, цифр і підкреслень, розмежована на обох кінцях:

    • Символи, відмінні від букв, цифр чи підкреслення

    • Початок або кінець рядка

    • Початок або кінець буфера редагування

  2. Максимальна послідовність символів, окрім букв, цифр, підкреслень чи символів, з обох кінців розміщена на:

    • Буква, цифра, підкреслення
    • <blank> символів
    • Початок або кінець рядка
    • Початок або кінець буфера редагування
  3. Один або кілька послідовних порожніх рядків

  4. Перший символ у буфері редагування

  5. Останній не <newline>в буфері редагування

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.