Как сопоставить строку, содержащую только один экземпляр шаблона, с grep? - PullRequest
3 голосов
/ 19 января 2020

С учетом текстового файла, такого как этот, скажем phrases.txt с содержанием:

Hahahahahasdhfjshfjshdhfjhdf
Hahahaha!
jdsahjhshfjhfHahahaha!dhsjfhajhfjhf
Hahaha!Hahaha!
dfhjfsf
sdfjsjf Hahaha! djfhjsdfh
Ha! hdfshdfs
Ha! Ha! Ha!

Какая будет подходящая команда grep в bash, которая будет выводить только строки, содержащие только единичный случай смеха, когда смех определяется как строка вида Hahahahaha! с произвольным числом ha с. Первый H всегда является заглавным, а другие - нет, и строка должна заканчиваться на !. В моем примере команда egrep должна вывести:

Hahahaha!
jdsahjhshfjhfHahahaha!dhsjfhajhfjhf
sdfjsjf Hahaha! djfhjsdfh
Ha! hdfshdfs

Команда, которую я придумал, была:

egrep "(Ha(ha)*\!){1}" phrases.txt

Проблема с моей командой заключается в том, что она не только выводит строки только с одним появлением смеха. С моей командой также выводятся строки 4 (Hahaha!Hahaha!) и строка 8 (Ha! Ha! Ha!), а это не то, что мне нужно.

Есть ли хороший способ сделать это только с помощью grep?

Ответы [ 2 ]

2 голосов
/ 19 января 2020

с трубками все в порядке, затем

egrep '(Ha(ha)*!)' yourfile.txt | egrep -v '(Ha(ha)*!).*(Ha(ha)*!)'

сначала отфильтруйте хотя бы один смех, затем отфильтруйте те, у которых более одного смеха.

Примечание: только {1} повторяет предыдущий фрагмент, он не проверяет оставшуюся часть строки, чтобы утверждать, что есть только один. Так что a{1} и a на самом деле одинаковы.

0 голосов
/ 19 января 2020

Если вы используете GNU grep или pcregrep, поддерживающие регулярное выражение PCRE, вы можете использовать

grep -P '^(?!(?:.*Ha(ha)*!){2}).*Ha(ha)*!'

Шаблон:

^(?!(?:.*YOUR_PATTERN_HERE){2}).*YOUR_PATTERN_HERE

, где стоит YOUR_PATTERN_HERE для вашего паттерна вы хотите, чтобы он встречался в строке только один раз.

Подробности

  • ^ - начало стрига
  • (?!(?:.*YOUR_PATTERN_HERE){2}) - отрицательный прогноз, который не соответствует совпадению, непосредственно справа от текущего местоположения (здесь, начало строки), есть два последовательных вхождения
    • .* - любые 0+ символов кроме символы разрыва строки
    • YOUR_PATTERN_HERE - требуемый шаблон
  • .* - любые 0+ символов, кроме символов разрыва строки
  • YOUR_PATTERN_HERE - ваш требуемый шаблон.

См. онлайн-демонстрацию :

s="Hahahahahasdhfjshfjshdhfjhdf
Hahahaha!
jdsahjhshfjhfHahahaha!dhsjfhajhfjhf
Hahaha!Hahaha!
dfhjfsf
sdfjsjf Hahaha! djfhjsdfh
Ha! hdfshdfs
Ha! Ha! Ha!"
echo "$s" | grep -P '^(?!(?:.*Ha(ha)*!){2}).*Ha(ha)*!'

Выход:

Hahahaha!
jdsahjhshfjhfHahahaha!dhsjfhajhfjhf
sdfjsjf Hahaha! djfhjsdfh
Ha! hdfshdfs
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...