Как я могу найти количество слов из 8 букв, которые не содержат буквы «e», используя команду grep?

#linux #bash #unix #grep #wc

#linux #bash #unix #grep #wc

Вопрос:

Я хочу найти количество слов из 8 букв, которые не содержат буквы «e», в нескольких текстовых файлах (* .txt). В процессе я столкнулся с двумя проблемами: мое непонимание кванторов и как исключить символы.

Я совсем новичок в терминале Unix, но это то, что я пробовал:

 cat *.txt | grep -Eo "w " | grep -i ".*[^e].*"
  

Мне нужно включить команду cat, потому что в противном случае она включает имена текстовых файлов в канале. Второй канал должен содержать все слова в списке, и это работает, но последний канал предназначался для поиска всех слов, в которых нет буквы «e», но, похоже, не работает. (Я подумал «.» для no или любого количества любого символа, за которым следует символ, который не является «e», а затем другой «.» для no или любого количества любого символа.)

 cat *.txt | grep -Eo "w " | grep -wi "[a-z][a-z][a-z][a-z][a-z][a-z][a-z][a-z]"
  

Эта команда работает для поиска слов, содержащих 8 символов, но она довольно неэффективна, потому что мне приходится повторять «[a-z]» 8 раз. Я думал, что это также может быть «[a-z] {8}», но это, похоже, не работает.

 cat *.txt | grep -Eo "w " | grep -wi "[a-z][a-z][a-z][a-z][a-z][a-z][a-z][a-z]" | grep -i ".*[^e].*"
  

Итак, наконец, это было бы моим лучшим предположением, однако третий канал неэффективен, а последний канал не работает.

Комментарии:

1. Спасибо, что поделились своими усилиями в своем вопросе, продолжайте в том же духе. Не могли бы вы также поделиться примерами ввода и ожидаемого результата в вашем вопросе для большей ясности вопроса.

2. [a-z] — так исключите e , например [a-df-z] . "[a-z]{8}", but that doesn't seem to work. Я всегда путаюсь между базовым и расширенным регулярным выражением. В обычном grep do [a-z]{8} , grep -E тогда {8} это сработает.

3. @doelie247: вместо использования wc regex тега было бы более уместно, поскольку вы ищете не wc регулярное выражение, а регулярное выражение. Пожалуйста, отредактируйте свой вопрос соответствующим образом.

4.Вы могли бы написать какую-нибудь программу на C (см. n1570, затем системные вызовы (2) и регулярные выражения (7) …), или на C — скомпилированный GCC — на Python, в Ocaml их найти. Если у вас много файлов, это может быть более подходящим

5. Вас также могут заинтересовать glob(7) , readdir(3) и nftw(3) . Читайте также Advanced Linux Programming

Ответ №1:

Вы можете использовать это grep :

 grep -hEiwo '[a-df-z]{8}' *.txt
  

Здесь:

  • [a-df-z]{8} : Соответствует всем буквам, кроме e
  • -h : Не выводить имя файла в выходных данных
  • -i : Игнорировать поиск по регистру
  • -o : Только совпадения для печати
  • -w : Сопоставление полных слов

Ответ №2:

В случае, если вы согласны с GNU awk и предполагаете, что вы хотите печатать только точные слова и в строке может быть несколько совпадений, если это так, можно попробовать следующее.

 awk -v IGNORECASE="1" '{for(i=1;i<=NF;i  ){if($i~/^[a-df-z]{8}$/){print $i}}}' *.txt
  

ИЛИ без использования IGNORCASE можно попробовать:

 awk '{for(i=1;i<=NF;i  ){if(tolower($i)~/^[a-df-z]{8}$/){print $i}}}' *.txt
  

ПРИМЕЧАНИЕ: учитывая, что вам нужны точные совпадения только из 8 букв в строках. слова из 8 букв, за которыми следует знак препинания, будут исключены.

Ответ №3:

Вот сумасшедшая мысль с GNU awk:

 awk 'BEGIN{FPAT="\<\w{8}\>"}{c =NF}END{print c}' file
  

Или, если вы хотите, чтобы он работал только с выбранным набором символов:

 awk 'BEGIN{FPAT="\<[a-df-z]{8}\>"}{c =NF}END{print c}' file
  

Что это делает, так это определяет поля как набор из 8 символов ( w как составную часть слова или [a-df-z] как выбранный набор), который заключен в границы слов ( < и > ). Это делается с FPAT помощью (обратите внимание на кровавые подробности об экранировании).

Иногда у вас также могут быть слова, содержащие диатрибу, поэтому вам нужно расширить. Тогда это может быть лучшим решением:

 awk 'BEGIN{FPAT="\<\w{8}\>"}{for(i=1;i<=NF;  i) if($i !~ /e/) c  }END{print c}' file