LINUX.ORG.RU

Регулярное выражение grep: содержит bcd и не содержит bcde - одной регуляркой

 , ,


0

1

Привет

Помогите, плиз, написать регуляркe для grep.
Важно: два grep'а и/или grep -v не предлагать.
Допустимо: grep -P - Perl-compatible regular expression (PCRE)

Условие: содержит bcd и не содержит bcde
Аналог с двумя grep'ами:

grep -P 'bcd' <<<"abcdefghij" | grep -P '^((?!bcde).)*$'
Тесткейсы:
grep '???' <<<"abcdefghij" -> ""
grep '???' <<<"abcd_efghij" -> "abcd_efghij"
grep '???' <<<"abcd_efghijbcde" -> ""
grep '???' <<<"bcdeabcd_efghij" -> ""

Спасибо.

★★★★★

Последнее исправление: Kroz (всего исправлений: 2)
Ответ на: комментарий от ABW

Да, я вот это искал. Хоть и не grep, но к моей задаче подходит.
Спасибо.

Kroz ★★★★★
() автор топика
Ответ на: комментарий от Deleted

Мдя, документацию ты читать не можешь.

А у тебя, похоже, с чтением ТЗ проблемы.

https://www.regular-expressions.info/lookaround.html
Negative lookahead provides the solution: q(?!u)

Теперь внимательно посмотри на второй grep в grep -P 'bcd' <<<"abcdefghij" | grep -P '^((?!bcde).)*$'.

Kroz ★★★★★
() автор топика
Ответ на: комментарий от Kroz

Не работает

grep -P 'bcd(?!e)'

upd. А, посмотрел примеры, не работает.

pru-mike ★★
()
Последнее исправление: pru-mike (всего исправлений: 1)

На чистом Перле будет как-то так:

perl -ne 'print if /^(?=.*bcd)(?!.*bcde).*/'

Под рукой нет grep -P. Проверьте. По идее, там тоже должно работать.

evbogdanov
()

на awk наиболее читаемо получается

awk '/bcd/ && !/bcde/'

/bcd/ и-не /bcde/

futurama ★★★★★
()
Ответ на: комментарий от evbogdanov

Работает. То, что нужно. Спасибо.

grep -P '^(?=.*bcd)(?!.*bcde).*' <<<"abcdefghij" -> ""
grep -P '^(?=.*bcd)(?!.*bcde).*' <<<"abcd_efghij" -> "abcd_efghij"
grep -P '^(?=.*bcd)(?!.*bcde).*' <<<"abcd_efghijbcde" -> ""
grep -P '^(?=.*bcd)(?!.*bcde).*' <<<"bcdeabcd_efghij" -> ""

Kroz ★★★★★
() автор топика
Ответ на: комментарий от Kroz

Более кошерная регулярка от Шинкаге (@zhmylove):

grep -P '^(?(?=.*bcde)(*F)).*bcd'

# Test cases:
grep -P '^(?(?=.*bcde)(*F)).*bcd' <<<"abcdefghij" -> ""
grep -P '^(?(?=.*bcde)(*F)).*bcd' <<<"abcd_efghij" -> "abcd_efghij"
grep -P '^(?(?=.*bcde)(*F)).*bcd' <<<"abcd_efghijbcde" -> ""
grep -P '^(?(?=.*bcde)(*F)).*bcd' <<<"bcdeabcd_efghij" -> ""

conformist ★★★
()
Ответ на: комментарий от conformist

Если строки длинные и требуется производительный матчинг, то самый быстрый вариант вот такой:

grep -P 'bcd(*COMMIT)(?!e|.*bcde)'

conformist ★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.