842

有没有办法让 grep 从匹配搜索表达式的文件中输出“单词”?

如果我想在多个文件中找到“th”的所有实例,我可以这样做:

grep "th" *

但输出将类似于(粗体是我的);

some-text-file :坐在垫子  
some-other-text-file :快速棕色狐狸  
另一个文本文件:我希望这能彻底解释 

我希望它使用相同的搜索输出的是:

the
the
the
this
thoroughly

这可能使用grep吗?还是使用其他工具组合?

4

14 回答 14

1201

尝试grep -o

grep -oh "\w*th\w*" *

编辑:匹配菲尔的评论。

文档

-h, --no-filename
    Suppress the prefixing of file names on output. This is the default
    when there is only  one  file  (or only standard input) to search.
-o, --only-matching
    Print  only  the matched (non-empty) parts of a matching line,
    with each such part on a separate output line.
于 2009-10-10T01:01:36.047 回答
98

交叉分发安全答案(包括 windows minGW?)

grep -h "[[:alpha:]]*th[[:alpha:]]*" 'filename' | tr ' ' '\n' | grep -h "[[:alpha:]]*th[[:alpha:]]*"

如果您使用的是不包含 -o 选项的旧版本的 grep(如 2.4.2),请使用上面的。否则使用下面更简单的维护版本。

Linux 跨发行版安全答案

grep -oh "[[:alpha:]]*th[[:alpha:]]*" 'filename'

总结一下:-oh输出与文件内容(而不是文件名)匹配的正则表达式,就像您期望正则表达式在 vim/etc 中的工作方式一样......那么您要搜索的单词或正则表达式是由你决定!只要您仍然使用 POSIX 而不是 perl 语法(请参阅下文)

更多来自 grep 手册

-o      Print each match, but only the match, not the entire line.
-h      Never print filename headers (i.e. filenames) with output lines.
-w      The expression is searched for as a word (as if surrounded by
         `[[:<:]]' and `[[:>:]]';

原始答案不适用于所有人的原因

的用法\w因平台而异,因为它是扩展的“perl”语法。因此,那些仅限于使用 POSIX 字符类的 grep 安装使用[[:alpha:]]而不是其 perl 等效的\w. 有关更多信息,请参阅有关正则表达式的 Wikipedia 页面

最终,无论 grep 的平台(原始)如何,上面的 POSIX 答案都会更加可靠

至于对不带 -o 选项的 grep 的支持,第一个 grep 输出相关行, tr 将空格拆分为新行,最后一个 grep 仅针对相应行进行过滤。

(PS:我知道现在大多数平台都会为 \w 打补丁。但总有那些落后的)

归功于@AdamRosenfield 回答的“-o”解决方法

于 2013-04-14T08:17:27.853 回答
61

它比你想象的要简单。尝试这个:

egrep -wo 'th.[a-z]*' filename.txt #### (Case Sensitive)

egrep -iwo 'th.[a-z]*' filename.txt  ### (Case Insensitive)

在哪里,

 egrep: Grep will work with extended regular expression.
 w    : Matches only word/words instead of substring.
 o    : Display only matched pattern instead of whole line.
 i    : If u want to ignore case sensitivity.
于 2017-03-28T09:25:08.447 回答
49

您可以将空格转换为换行符,然后 grep,例如:

cat * | tr ' ' '\n' | grep th
于 2009-10-10T01:43:06.337 回答
44

只是awk,不需要工具的组合。

# awk '{for(i=1;i<=NF;i++){if($i~/^th/){print $i}}}' file
the
the
the
this
thoroughly
于 2009-10-10T00:54:12.160 回答
12

grep 命令仅用于匹配和 perl

grep -o -P 'th.*? ' filename
于 2012-11-29T09:11:26.607 回答
10

我对 awk 难以记忆的语法感到不满意,但我喜欢使用一个实用程序来做到这一点的想法。

似乎 ack (或者 ack-grep 如果你使用 Ubuntu)可以很容易地做到这一点:

# ack-grep -ho "\bth.*?\b" *

the
the
the
this
thoroughly

如果你省略 -h 标志,你会得到:

# ack-grep -o "\bth.*?\b" *

some-other-text-file
1:the

some-text-file
1:the
the

yet-another-text-file
1:this
thoroughly

作为奖励,您可以使用该--output标志使用我发现的最简单的语法来执行更复杂的搜索:

# echo "bug: 1, id: 5, time: 12/27/2010" > test-file
# ack-grep -ho "bug: (\d*), id: (\d*), time: (.*)" --output '$1, $2, $3' test-file

1, 5, 12/27/2010
于 2011-01-11T21:25:48.313 回答
9
cat *-text-file | grep -Eio "th[a-z]+"
于 2010-09-14T15:30:51.730 回答
4

您也可以尝试pcregrepgrep中还有一个-w选项,但在某些情况下它不能按预期工作。

来自维基百科

cat fruitlist.txt
apple
apples
pineapple
apple-
apple-fruit
fruit-apple

grep -w apple fruitlist.txt
apple
apple-
apple-fruit
fruit-apple
于 2009-11-14T12:15:02.517 回答
4

要搜索以“icon-”开头的所有单词,以下命令可以完美运行。我在这里使用Ack,它与 grep 类似,但具有更好的选项和良好的格式。

ack -oh --type=html "\w*icon-\w*" | sort | uniq
于 2014-01-16T15:46:55.197 回答
3

我有一个类似的问题,寻找 grep/pattern 正则表达式和“找到的匹配模式”作为输出。

最后,我使用了 egrep(grep -e 或 -G 上的相同正则表达式没有给我与 egrep 相同的结果)和选项 -o

所以,我认为这可能类似于(我不是正则表达式大师):

egrep -o "the*|this{1}|thoroughly{1}" filename
于 2013-02-14T16:39:19.213 回答
-1

您可以像这样将 grep 输出通过管道传输到 Perl:

grep "th" * | perl -n -e'while(/(\w*th\w*)/g) {print "$1\n"}'
于 2009-10-10T01:06:09.370 回答
-2
$ grep -w

grep 手册页的摘录:

-w:仅选择那些包含构成整个单词的匹配项的行。测试是匹配的子字符串必须在行首,或者前面有一个非单词组成字符。

于 2012-05-29T06:32:31.807 回答
-8

ripgrep

以下是使用的示例ripgrep

rg -o "(\w+)?th(\w+)?"

它将匹配所有匹配的单词th

于 2018-11-07T12:38:46.677 回答