grep只能显示与搜索模式匹配的单词吗?

Can grep show only words that match search pattern?

有没有办法让grep从与搜索表达式匹配的文件中输出"words"?

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

1
grep"th" *

但是输出将是类似的(粗体由我决定);

1
2
3
some-text-file : the cat sat on the mat  
some-other-text-file : the quick brown fox  
yet-another-text-file : i hope this explains it thoroughly

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

1
2
3
4
5
the
the
the
this
thoroughly

是否可以使用grep?或者使用其他工具组合?


尝试GRPO

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

编辑:与菲尔的评论匹配

来自文档:

1
2
3
4
5
6
-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.


交叉分发安全答案(包括Windows Mingw?)

1
2
grep -h"[[:alpha:]]*th[[:alpha:]]*" 'filename' | tr ' ' '
' | grep -h"[[:alpha:]]*th[[:alpha:]]*"

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

Linux交叉分发安全答案

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

为了总结-oh输出与文件内容(而不是文件名)匹配的正则表达式,就像您希望正则表达式在vim/etc中工作一样。那么,您将要搜索的是什么单词或正则表达式呢?只要您继续使用POSIX而不是Perl语法(请参阅下面的内容)

更多关于grep的信息

1
2
3
4
-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。有关更多信息,请参见正则表达式上的维基百科页面。

最终,不管GREP的平台(原始版本)是什么,上面的POSIX答案都会更加可靠。

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

(附言:我知道大多数平台到目前为止,都已经为w…进行了修补。但总有落后的)

来自@adamrosenfield答案的"-o"解决方案


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

1
2
cat * | tr ' ' '
' | grep th


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

1
2
3
4
5
6
# awk '{for(i=1;i<=NF;i++){if($i~/^th/){print $i}}}' file
the
the
the
this
thoroughly


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

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

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

在哪里?

1
2
3
4
 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.


grep命令仅用于匹配和perl

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


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

似乎ack(如果使用ubuntu,则为ack grep)可以轻松做到这一点:

1
2
3
4
5
6
7
# ack-grep -ho"\bth.*?\b" *

the
the
the
this
thoroughly

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

1
2
3
4
5
6
7
8
9
10
11
12
# 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标志来执行此操作,其语法几乎是我发现的最简单的:

1
2
3
4
# 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

1
cat *-text-file | grep -Eio"th[a-z]+"


要搜索所有以"icon-"开头的单词,以下命令工作正常。我在这里使用的是ACK,它与grep类似,但具有更好的选项和良好的格式。

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

我也遇到了类似的问题,寻找grep/pattern regex和输出的"matched pattern found"。

最后,我使用了egrep(grep-e上的同一个regex或-g没有给出与egrep相同的结果)和选项-o

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

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


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

维基百科:

1
2
3
4
5
6
7
8
9
10
11
12
13
cat fruitlist.txt
apple
apples
pineapple
apple-
apple-fruit
fruit-apple

grep -w apple fruitlist.txt
apple
apple-
apple-fruit
fruit-apple


1
$ grep -w

摘自grep手册页:

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


ripgrep

下面是使用ripgrep的示例:

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

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


您可以这样将grep输出导入Perl:

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