Получите количество уникальных слов в файле, используя grep и wc

нужна команда, чтобы найти количество уникальных слов в файле с помощью grep

Пробовал использовать grep вместе с uniq и sort, но нужно найти способ использовать только команды grep и wc. Это два способа, которыми я могу это сделать, но мне нужно использовать только grep..

$ grep -oE '\w+' 'file.txt' | sort | uniq | wc -l
$ grep -oE '\w+' 'file.txt' > temp.txt && awk '!seen[$0]++' temp.txt | wc -l

Пример входного файла:

one two three four five
two four one six
eight three seven five

Выход: уникальное количество слов: 8

Можно ли сначала извлечь слова с помощью команды grep -oE '\w+' file.txt, затем выполнить grep для каждого слова в пустой файл и добавить слово в файл, если grep не находит слово, существующее в этом файле .таким образом к нему будут добавлены только те слова, которых нет в новом файле? можно ли это сделать с помощью grep?

Можете ли вы добавить минимальный (5–10 строк) пример с ожидаемым результатом?

Andre Wildberg 04.05.2024 16:57

@AndreWildberg, я добавил ожидаемый результат

anonymous 04.05.2024 17:12

Большое спасибо! Значит, в файле есть только слова, некоторые в одной строке, но также и с символами новой строки?

Andre Wildberg 04.05.2024 17:14

@AndreWildberg да, в файле есть только слова, например абзац с несколькими строками, содержащими слова.

anonymous 04.05.2024 17:15

Кстати, 1) sort | uniq = sort -u и 2) grep -oE '\w+' 'file.txt' > temp.txt && awk '!seen[$0]++' temp.txt = grep -oE '\w+' 'file.txt' | awk '!seen[$0]++'.

Ed Morton 04.05.2024 17:51

почему нельзя использовать sort? это своего рода домашнее задание/лабораторное задание, и если да, то каковы полные требования/ограничения? вы ожидаете, что сделаете все это, используя только grep и wc?

markp-fuso 04.05.2024 17:54

@markp-fuso просто пытается расширить функциональность grep без использования сортировки. Требуется просто получить количество уникальных слов в файле с помощью grep и wc, возможно, также можно использовать find

anonymous 04.05.2024 18:53

«Когда выдающийся, но пожилой учёный утверждает, что что-то возможно, он почти наверняка прав. Когда он утверждает, что что-то невозможно, он, скорее всего, ошибается».

jhnc 05.05.2024 16:57

@jhnc, честно говоря, я не рассматривал более эзотерические сценарии, которые могли бы быть возможны с помощью GNU grep и его расширений, учитывая некоторые важные предостережения!

Ed Morton 05.05.2024 17:45
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
9
164
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Поскольку awk также помечен тегами, подход использует только (почти любой) awk, возвращая длину ассоциативного массива, где индексами являются слова.

% awk '{for(i=1;i<=NF;i++){A[$i]++}} END{print length(A)}' file
8

Протестировано с

  • GNU awk 3.1.8/4.2.1/5.3.0
  • нак 20221215
  • оригинальный awk 20121220
  • чувак 20240123

То, что вы хотите сделать, невозможно с помощью всего лишь grep или grep+wc (если только вы не используете GNU grep с его расширениями и предостережениями согласно ответу @jhnc).

Учитывая это, если вы действительно хотите использовать только один инструмент, используйте GNU Awk для многосимвольных символов RS и примите в качестве входных данных файл, состоящий из «слов», разделенных пробелами:

$ awk -v RS='\\s+' '{unq[$0]} END{print "unique word count:", length(unq)}' file.txt
unique word count: 8

или используя регулярное выражение для идентификации «слова»:

$ awk -v RS='\\w+' 'RT{unq[RT]} END{print "unique word count:", length(unq)}' file.txt
unique word count: 8
Ответ принят как подходящий

Поскольку у вашего grep есть -o, я предполагаю, что у него также есть -P и -z:

grep -zPo '(?s)(\b\w+\b)(?!.*\b\1\b)' file.txt |
grep -zc ^
  • используйте -z, чтобы grep рассматривал весь файл как одну «строку» (поскольку в нем не должно быть нулей)
  • используйте -P, чтобы включить Perl-совместимые регулярные выражения (PCRE), которые позволяют выполнять обходные утверждения
  • (?s) — сообщить PCRE, что . также должно соответствовать символу новой строки.
  • используйте отрицательный просмотр вперед (?! ... ), чтобы найти последнее вхождение каждого слова (т. е. за словом, за которым не следует ничего, за которым следует само себя)
    • \b\w+\b и \b\1\b исключить части слов
  • мы используем предварительный просмотр, чтобы предпросмотренный текст не поглощался совпадением и мог быть повторно использован при поиске дополнительных окончательных слов.
  • используйте -o для вывода каждого совпадения в отдельной «строке» (из-за -z в качестве символа конца строки используются нули)
  • возьмите сгенерированный список уникальных слов и выведите количество «строк»

Это будет очень медленно для больших файлов.

Сейчас я немного думаю о том, что делает этот сценарий. Согласно справочной странице GNU grep о -P «Этот параметр является экспериментальным в сочетании с параметром -z (--null-data)», знаете ли вы, является ли что-либо из приведенного выше хрупким в этом контексте?

Ed Morton 05.05.2024 17:42

@EdMorton, учитывая, что RE страдает от катастрофического возврата, хрупкость - наименьшая из его проблем.

jhnc 05.05.2024 17:45

@EdMorton regex101 достигает 40M шагов для ввода 3500 слов и тайм-аута с 4000, намного больше, и это, скорее всего, сломается

jhnc 05.05.2024 17:51

ну, ОП только что спросил, можно ли это сделать, а не можно ли это сделать надежно, портативно, эффективно, надежно и т. д., так что, по моему мнению, это хороший ответ :-).

Ed Morton 05.05.2024 17:51

да, для любого ввода значительного размера просто использовать sort -u намного надежнее

jhnc 05.05.2024 18:24

TIL -o нет в POSIX grep

tripleee 05.05.2024 18:29

Другие вопросы по теме