grep可以只显示匹配搜索模式的单词吗?

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

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

grep "th" *

但输出将是这样的(粗体是我);

some-text-file : the cat sat on the matsome-other-text-file : the quick brown foxyet-another-text-file : i hope this explains it thoroughly

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

thethethethisthoroughly

这可能使用grep吗?或者使用其他工具组合?

1006975 次浏览

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

# awk '{for(i=1;i<=NF;i++){if($i~/^th/){print $i}}}' filethethethethisthoroughly

尝试grep -o

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

编辑:匹配菲尔的评论。

的文档

-h, --no-filenameSuppress the prefixing of file names on output. This is the defaultwhen there is only  one  file  (or only standard input) to search.-o, --only-matchingPrint  only  the matched (non-empty) parts of a matching line,with each such part on a separate output line.

你可以像这样将grep输出管道到Perl中:

grep "th" * | perl -n -e'while(/(\w*th\w*)/g) {print "$1\n"}'

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

cat * | tr ' ' '\n' | grep th

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

维基百科

cat fruitlist.txtappleapplespineappleapple-apple-fruitfruit-apple
grep -w apple fruitlist.txtappleapple-apple-fruitfruit-apple
cat *-text-file | grep -Eio "th[a-z]+"

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

看起来ack(如果您使用Ubuntu,则为ack-grep)可以轻松做到这一点:

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

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

# ack-grep -o "\bth.*?\b" *
some-other-text-file1:the
some-text-file1:thethe
yet-another-text-file1:thisthoroughly

作为奖励,您可以使用--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
$ grep -w

摘自grep man page:

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

grep命令仅匹配和perl

grep -o -P 'th.*? ' filename

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

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

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

egrep -o "the*|this{1}|thoroughly{1}" filename

交叉分布安全答案(包括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:]]而不是与\w等效的perl。有关更多信息,请参阅正则表达式的维基百科页面

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

至于没有-o选项的grep支持,第一个grep输出相关行,tr将空格拆分为新行,最后的grep过滤器仅用于相应的行。

(PS:我知道现在大多数平台都已经为\w……但总有那些落后的)

来自@AdamRosenfield答案的“-o”解决方案

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

ack -oh --type=html "\w*icon-\w*" | sort | uniq

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

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.

ripgrep

以下是使用ripgrep的示例:

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

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

grep --color -o -E "Begin.{0,}?End" file.txt

?-尽可能少的匹配,直到End

在macos终端上测试