Может ли grep показывать только слова, соответствующие шаблону поиска?
Есть ли способ сделать grep вывод "слов" из файлов, соответствующих выражению поиска?
Если я хочу найти все экземпляры, скажем, "th" в нескольких файлах, я могу сделать:
grep "th" *
но результат будет чем-то вроде (жирный - мной);
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
Я хочу, чтобы он выводил, используя тот же поиск:
the
the
the
this
thoroughly
Можно ли использовать grep? Или используя другую комбинацию инструментов?
Ответы
Ответ 1
Попробуйте 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.
Ответ 2
Безопасный ответ на кросс-дистрибуцию (включая окна minGW?)
grep -h "[[:alpha:]]*th[[:alpha:]]*" 'filename' | tr ' ' '\n' | grep -h "[[:alpha:]]*th[[:alpha:]]*"
Если вы используете старые версии grep (например, 2.4.2), которые не включают опцию -o. Используйте приведенное выше. Else использовать более простой для поддержки версии ниже.
Безопасный ответ перекрестного распределения 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". Таким образом, те установки grep, которые ограничены работой с классами символов POSIX, используют [[:alpha:]]
, а не его perl-эквивалент \w
. Подробнее см. на странице Википедии о регулярном выражении
В конечном счете, ответ POSIX выше будет намного надежнее независимо от платформы (являющейся оригиналом) для grep
Что касается поддержки grep без опции -o, первый grep выводит соответствующие строки, tr разбивает пробелы на новые строки, последние grep фильтруют только для соответствующих строк.
(PS: Я знаю большинство платформ к настоящему времени, был бы исправлен для \w.... но всегда есть те, которые отстают)
Кредит для обхода "-o" из ответа @AdamRosenfield
Ответ 3
Вы можете перевести пробелы в новые строки, а затем grep, например:
cat * | tr ' ' '\n' | grep th
Ответ 4
Просто awk
, нет необходимости в комбинации инструментов.
# awk '{for(i=1;i<=NF;i++){if($i~/^th/){print $i}}}' file
the
the
the
this
thoroughly
Ответ 5
Это проще, чем вы думаете. Попробуйте следующее:
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.
Ответ 6
команда grep только для соответствия и perl
grep -o -P 'th.*? ' filename
Ответ 7
cat *-text-file | grep -Eio "th[a-z]+"
Ответ 8
Я был неудовлетворен сильным синтаксисом 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
Ответ 9
Для поиска всех слов с начала с помощью "icon-" следующая команда работает идеально. Я использую Ack здесь, который похож на grep, но с лучшими параметрами и красивым форматированием.
ack -oh --type=html "\w*icon-\w*" | sort | uniq
Ответ 10
Вы также можете попробовать pcregrep. В grep есть опция -w
, но в некоторых случаях она не работает должным образом.
От Wikipedia:
cat fruitlist.txt
apple
apples
pineapple
apple-
apple-fruit
fruit-apple
grep -w apple fruitlist.txt
apple
apple-
apple-fruit
fruit-apple
Ответ 11
У меня была аналогичная проблема, ища регулярное выражение grep/pattern и "сопоставленный шаблон найден" как вывод.
В конце я использовал egrep (одно и то же регулярное выражение на grep -e или -G не дало мне того же результата egrep) с опцией -o
поэтому, я думаю, что это может быть что-то похожее (я не являюсь мастером регулярных выражений):
egrep -o "the*|this{1}|thoroughly{1}" filename
Ответ 12
Вы можете передать свой вывод grep в Perl следующим образом:
grep "th" * | perl -n -e'while(/(\w*th\w*)/g) {print "$1\n"}'
Ответ 13
$ grep -w
Выдержка из страницы grep man:
-w: Выберите только те строки, которые содержат совпадения, которые образуют целые слова. Тест состоит в том, что совпадающая подстрока должна либо находиться в начале строки, либо предшествовать неклассическому составляющему символу.
Ответ 14
Вот пример использования ripgrep
:
rg -o "(\w+)?th(\w+)?"
Это будет соответствовать всем словам, совпадающим с th
.