#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