wc -w 命令输出错误答案

J.D*_*Doe 2 grep wc

我必须找出在一个文件中使用 shell 这个词的次数。我用grep "shell" test.txt | wc -w是为了统计这个词被使用了多少次,结果是4而不是3。文件内容是:

this is a test file
for shell_A
shell_B
sh
shel
and 
shell_C
script project
Run Code Online (Sandbox Code Playgroud)

Tho*_*key 18

wc 命令正在计算 grep 输出中的单词,其中包括“for”:

> grep shell test.txt
for shell_A
shell_B
shell_C
Run Code Online (Sandbox Code Playgroud)

所以真的有4个字。

如果您只想计算文件中包含特定单词的行数,可以使用-cgrep 选项,例如,

grep -c shell test.txt
Run Code Online (Sandbox Code Playgroud)

这两个实际上都不计算单词,但可以匹配包含该字符串的其他内容。的大多数实现grep(GNU grep的,现代的BSD系统以及AIX,HPUX,Solaris)上提供了一个-w单词的选择,但是是不是在POSIX。它们还识别正则表达式,例如,

grep -e '\<shell\>' test.txt
Run Code Online (Sandbox Code Playgroud)

这对应于-w选项。同样,不在 POSIX 中。Solaris 确实记录了这一点,而 AIX 和 HPUX-w没有提及正则表达式。这些似乎都是一致的,将“单词”视为字母数字加下划线的序列。

您可以使用带有 grep 的 POSIX 正则表达式来匹配单词(由空格等分隔),但您的示例没有一个只是“shell”:它们都有一些其他字符接触匹配项。或者,如果您只关心字母数字(没有下划线)并且不介意匹配子字符串,您可以这样做

tr -c '[[:alnum:]]' '\n' test.txt |grep -c shell
Run Code Online (Sandbox Code Playgroud)

-o建议的选项是非 POSIX,并且由于 OP 没有将问题限制在 Linux 或 BSD 上,因此我不建议这样做。无论哪种情况,它都不匹配words,而是匹配strings(这是 OP 的期望)。

以供参考:

  • 而且您必须小心使用(理论上的)输入行,例如“shell shell” (2认同)

Dyl*_*lan 16

命令“grep”正在输出“shell”出现的整行。不仅仅是“壳”这个词。如下所示:

grep shell test.txt
for shell_A
shell_B
shell_C
Run Code Online (Sandbox Code Playgroud)

我建议使用该选项

-o, --only-matching

所以:

grep -o "shell" test.txt | wc -w
Run Code Online (Sandbox Code Playgroud)


Ant*_*hon 5

因为你可以在一行上多次使用“shell”这个词,所以我会首先将文本分解为每行单个单词,然后执行 grep

< test.txt tr -s "[[:blank:]]" "\n" | grep "shell" | wc -w
Run Code Online (Sandbox Code Playgroud)

您也可以使用wc -l,或取消wc并使用grep -c "shell"

您甚至可以消除对tr您拥有和使用的文件的需求:

grep -c "shell" test.txt

  • @J.Doe 然后省略我在更新答案中显示的 `tr`。`grep -c "shell" test.txt` 给你 3,但仅仅是因为一行上没有双“shell” (3认同)
  • 我发现你的回答很色情并且很喜欢。但是对于涉及许多复杂主题的 shell 脚本的新手来说。仍然得到了我的投票 (2认同)