Can grep show only words that match search pattern

2019-01-01 01:30发布

Is there a way to make grep output "words" from files that match the search expression?

If I want to find all the instances of, say, "th" in a number of files, I can do:

grep "th" *

but the output will be something like (bold is by me);

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 

What I want it to output, using the same search, is:

the
the
the
this
thoroughly

Is this possible using grep? Or using another combination of tools?

标签: grep words
14条回答
残风、尘缘若梦
2楼-- · 2019-01-01 01:49

You could pipe your grep output into Perl like this:

grep "th" * | perl -n -e'while(/(\w*th\w*)/g) {print "$1\n"}'
查看更多
孤独寂梦人
3楼-- · 2019-01-01 01:54

I was unsatisfied with awk's hard to remember syntax but I liked the idea of using one utility to do this.

It seems like ack (or ack-grep if you use Ubuntu) can do this easily:

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

the
the
the
this
thoroughly

If you omit the -h flag you get:

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

some-other-text-file
1:the

some-text-file
1:the
the

yet-another-text-file
1:this
thoroughly

As a bonus, you can use the --output flag to do this for more complex searches with just about the easiest syntax I've found:

# 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
查看更多
余欢
4楼-- · 2019-01-01 01:55

Cross distribution safe answer (including windows minGW?)

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

If your using older versions of grep (like 2.4.2) which does not include the -o option. Use the above. Else use the simpler to maintain version below.

Linux cross distribution safe answer

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

To summaries -oh outputs the regular expression matches to the file content (and not its filename), just like how you would expect regular expression to work in vim/etc... What word or regular expression you would be searching for then, is up to you! As long as you remain to POSIX and not perl syntax (refer below)

More from the manual for 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 `[[:>:]]';

The reason why the original answer does not work for everyone

The usage of \w varies from platform to platform, as its an extended "perl" syntax. As such, those grep installation that is limited to work with POSIX character classes uses [[:alpha:]] and not its perl equivalent of \w. See the Wikipedia page on regular expression for more

Ultimately, the POSIX answer above will be alot more reliable regardless of platform (being the original) for grep

As for support of grep without -o option, the first grep outputs the relevant lines, the tr splits the spaces to new lines, the final grep filters only for the respective lines.

(PS: I know most platforms by now, would have been patched for \w.... but there are always those that lag behind)

Credit for the "-o" workaround from @AdamRosenfield answer

查看更多
弹指情弦暗扣
5楼-- · 2019-01-01 01:55

Just awk, no need combination of tools.

# awk '{for(i=1;i<=NF;i++){if($i~/^th/){print $i}}}' file
the
the
the
this
thoroughly
查看更多
旧人旧事旧时光
6楼-- · 2019-01-01 01:55
$ grep -w

Excerpt from grep man page:

-w: Select only those lines containing matches that form whole words. The test is that the matching substring must either be at the beginning of the line, or preceded by a non-word constituent character.

查看更多
一个人的天荒地老
7楼-- · 2019-01-01 01:56

You can also try pcregrep. There is also a -w option in grep, but in some cases it doesn't work as expected.

From Wikipedia:

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

grep -w apple fruitlist.txt
apple
apple-
apple-fruit
fruit-apple
查看更多
登录 后发表回答