如何计算文件中的单词总数?


Answers:


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
请注意,也就是说对于wc -w不具有相同的定义GNU grep -w。对于wc一个字是一个或多个非空格字符的序列([:space:]在当前区域设置字符类)。例如foo,barfoo bar(与非打破空间)是每一个字。
斯特凡Chazelas

7

我想出这个只是数字:

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

5

我也喜欢这种wc -w < [file]方法

最后,仅将单词计数存储在变量中,可以使用以下命令:

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

这使您可以优雅地跳过文件名。


14
wc -w < "$file"只是数字。
斯特凡Chazelas

3

更好的解决方案是使用Perl:

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

@伯恩哈德

您可以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
为什么这比wc更好?
Sparr

2
@Sparr是一件事,因为令我非常惊讶的是,它似乎快得多。我在一个包含141813504个单词的文本文件上尝试了它,wc花了〜14秒,而Perl花了〜5秒!
terdon

3
我认为“更大”的问题确实是对Perl的依赖,而我从来都不喜欢这种依赖。如果问题是关于性能的,那将是另一回事。
Michael Durrant 2013年

5
请注意,一个split/\s+/就像是一个split(' ')不同之处在于任何前导空格产生空第一个字段。这种差异将为您每个线路 链接增加一个单词(第一个字段为空)。因此,(split(" ", $_))对于这样创建的文件,请另外使用:echo -e "unix\n linux" > testfile您的单行报告3个单词。
don_crissti

1
您的计时表明wc更快(这是用户和系统时间的重要所在)。使用LC_ALL = C时,wc速度将明显更快,就像使用时一样PERLIO=:utf8perl速度将明显慢。
斯特凡Chazelas

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-ward Ruby


它很重要,所以对我来说已经足够了!:-)
aggsol

3

wc程序会计算“单词”,但是例如,这些单词并不是许多人检查文件时会看到的“单词”。vi例如,该程序使用不同的“单词”量度,根据它们的字符类对它们进行定界,同时wc仅计算由空格分隔的内容。两种措施可能根本不同。考虑以下示例:

first,second

vi看到三个单词(第一个第二个,以及用逗号隔开),而wc看到一个单词(该行上没有空格)。数词的方法有很多,有些没有其他有用。

虽然Perl的会更适合写一个计数器vi风格的话,这里有一个简单的例子使用sedtrwc(适度便携使用文字回车^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个单词。
  • @cuonglm在Perl中的示例给出31。
  • 使用wc给出28。

作为参考,POSIX vi表示:

在POSIX语言环境中,vi将识别五种单词:

  1. 字母,数字和下划线的最大序列,两端用以下字符分隔:

    • 字母,数字或下划线以外的字符

    • 行的开头或结尾

    • 编辑缓冲区的开始或结束

  2. 除字母,数字,下划线或字符外的最大字符序列,两端用以下字符分隔:

    • 字母,数字,下划线
    • <blank> 人物
    • 行的开头或结尾
    • 编辑缓冲区的开始或结束
  3. 一或多个连续的空白行

  4. 编辑缓冲区中的第一个字符

  5. <newline>编辑缓冲区中的最后一个非

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.