RegEx для захвата содержимого между звездочками, кроме слова - PullRequest
4 голосов
/ 08 июня 2019

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

* apple *  * orange tasty *  * banana *  * grape NOT *

Ожидаемые результаты:

apple

orange tasty

banana

Ответы [ 5 ]

2 голосов
/ 08 июня 2019

Вы можете использовать следующее регулярное выражение: \*(\s*(?!NOT)\w+)+\s*\*

См. Пояснение к regex101 ...

enter image description here

Здесь вы можете визуализировать свое регулярное выражение ...

1 голос
/ 08 июня 2019

Не прочитал все ответы, но Мистер. Ответ Мортона весьма проницательный.

Этот вопрос также очень интересен, так как к нему можно подойти, и мы начнем с выражения, которое собирает наши NOT слова, используя границу слова, измененную желаемыми результатами. Наконец, мы проводим от начала до конца нашей строки, что может остаться, особенно если мы хотим заменить, но эта последняя часть не нужна:

(?:(\bNOT\b).)*|([\w\s]+?)|(.*?)

Здесь у нас есть две нежелательные группы:

(?:(\bNOT\b).)*

и

(.*?)

и наши нужные данные находятся во второй группе захвата:

([\w\s]+?)

, который можно просто изменить, если у нас больше желаемых символов, чем указано в нашем классе символов: [\w\s].

RegEx

Если это выражение нежелательно и вы хотите изменить его, перейдите по этой ссылке на regex101.com .

RegEx Circuit

jex.im визуализирует регулярные выражения:

enter image description here

Демо

1 голос
/ 08 июня 2019

Некоторые люди, сталкиваясь с проблемой, думают: «Я знаю, я буду использовать регулярные выражения».Теперь у них есть две проблемы.

С GNU awk для RS и RT с несколькими символами:

$ awk -v RS='[*][^*]+[*]' 'RT !~ /NOT/{print RT}' file
* apple *
* orange tasty *
* banana *

С любым awk в любой оболочке на каждом компьютере UNIX:

$ awk '{ while ( match($0,/[*][^*]+[*]/) ) {str=substr($0,RSTART,RLENGTH); if (str !~ /NOT/) print str; $0=substr($0,RSTART+RLENGTH)} }' file
* apple *
* orange tasty *
* banana *

Выше решена проблема с парой тривиальных регулярных выражений вместо одного сложного регулярного выражения.Удалить * s на каждом конце вывода тривиально, но я чувствую, что OP захочет вместо этого использовать какое-то запутанное одиночное регулярное выражение.

1 голос
/ 08 июня 2019

Вы можете использовать SKIP FAIL и \K, чтобы забыть, что было согласовано на текущий момент:

\*[^*]* NOT [^*]*\*(*SKIP)(*FAIL)|\*\s*\K\w+(?: \w+)*(?= \*)

Пояснение

  • \*[^*]* NOT [^*]*\* СоответствиеНЕ между звездочкой и пробелом, используя отрицательный символьный класс
  • (*SKIP)(*FAIL) Пропустить совпадающее
  • | Или
  • \*\s*\K Совпадение звездочек, 0+ пробельных символов изабыть то, что было найдено
  • \w+(?: \w+)* Совпадение 1+ символов слова и повторяющегося шаблона для соответствия пробелу и 1+ словам символов
  • (?= \*) Позитивный взгляд вперед, утверждают, что справапробел и звездочка

Regex demo | grep demo

Например:

echo "* apple * * orange tasty * * banana * * grape NOT *" | grep -Po "\*[^*]* NOT [^*]*\*(*SKIP)(*FAIL)|\*\s*\K\w+(?: \w+)*(?= \*)"

Результат

apple
orange tasty
banana
0 голосов
/ 08 июня 2019

Вы можете использовать это также для извлечения других данных в другой группе:

\*\s?(?:([a-zA-Z0-9 ]+?NOT))\s?\*|\*\s?([a-zA-Z0-9 ]+?)\s?\*

Это также работает в других движках регулярных выражений.Проверьте это здесь .
Визуальный Embeded :

<iframe frameborder="0" width="746" height="562" src="https://jex.im/regulex/#!embed=true&flags=&re=%5C*%5Cs%3F(%3F%3A(%5Ba-zA-Z0-9%20%5D%2B%3FNOT))%5Cs%3F%5C*%7C%5C*%5Cs%3F(%5Ba-zA-Z0-9%20%5D%2B%3F)%5Cs%3F%5C*"></iframe>
...