Регулярное выражение для соответствия строке, не содержащей слова - PullRequest
3957 голосов
/ 02 января 2009

Я знаю, что можно сопоставить слово, а затем отменить совпадения, используя другие инструменты (например, grep -v). Однако возможно ли сопоставить строки, которые не содержат конкретного слова, например, hede, используя регулярное выражение?

Введите:

hoho
hihi
haha
hede

Код:

grep "<Regex for 'doesn't contain hede'>" input

Желаемый вывод:

hoho
hihi
haha

Ответы [ 28 ]

7 голосов
/ 18 февраля 2015

Это может быть более удобным для двух регулярных выражений в вашем коде, один для первого совпадения, а затем, если он совпадает, запустите второе регулярное выражение, чтобы проверить наличие выбросов, которые вы хотите заблокировать, например, ^.*(hede).*, затем иметь соответствующую логику в ваш код.

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

5 голосов
/ 25 июня 2014

Язык TXR поддерживает отрицание регулярного выражения.

$ txr -c '@(repeat)
@{nothede /~hede/}
@(do (put-line nothede))
@(end)'  Input

Более сложный пример: сопоставить все строки, которые начинаются с a и заканчиваются z, но не содержат подстроку hede:

$ txr -c '@(repeat)
@{nothede /a.*z&~.*hede.*/}
@(do (put-line nothede))
@(end)' -
az         <- echoed
az
abcz       <- echoed
abcz
abhederz   <- not echoed; contains hede
ahedez     <- not echoed; contains hede
ace        <- not echoed; does not end in z
ahedz      <- echoed
ahedz

Отрицание регулярных выражений не особенно полезно само по себе, но когда у вас также есть пересечение, вещи становятся интересными, так как у вас есть полный набор операций с булевыми множествами: вы можете выразить "набор, который соответствует этому, за исключением вещей, которые соответствуют этому ».

4 голосов
/ 21 декабря 2016

Следующая функция поможет вам получить желаемый результат

<?PHP
      function removePrepositions($text){

            $propositions=array('/\bfor\b/i','/\bthe\b/i'); 

            if( count($propositions) > 0 ) {
                foreach($propositions as $exceptionPhrase) {
                    $text = preg_replace($exceptionPhrase, '', trim($text));

                }
            $retval = trim($text);

            }
        return $retval;
    }


?>
1 голос
/ 25 апреля 2018

Возможно, вы найдете это в Google, пытаясь написать регулярное выражение, способное сопоставлять сегменты строки (в отличие от целых строк), которые не содержат подстроку. Уделите мне немного времени, чтобы разобраться, и я поделюсь:

С учетом строки: <span class="good">bar</span><span class="bad">foo</span><span class="ugly">baz</span>

Я хочу сопоставить <span> теги, которые не содержат подстроку «bad».

/<span(?:(?!bad).)*?> будет соответствовать <span class=\"good\"> и <span class=\"ugly\">.

Обратите внимание, что есть два набора (слоя) скобок:

  • Самый внутренний - для негативного взгляда (это не группа захвата)
  • Самое внешнее было интерпретировано Ruby как группа захвата, но мы не хотим, чтобы это была группа захвата, поэтому я добавил?: В начале, и он больше не интерпретируется как группа захвата.

Демонстрация в Ruby:

s = '<span class="good">bar</span><span class="bad">foo</span><span class="ugly">baz</span>'
s.scan(/<span(?:(?!bad).)*?>/)
# => ["<span class=\"good\">", "<span class=\"ugly\">"]
1 голос
/ 11 октября 2017

Как использовать контрольные глаголы PCRE для отслеживания строки, не содержащей слова

Вот метод, который я раньше не видел:

/.*hede(*COMMIT)^|/

Как это работает

Сначала он пытается найти «хеде» где-то в строке. В случае успеха на этом этапе (*COMMIT) сообщает двигателю не только не возвращаться в случае сбоя, но и не предпринимать попыток дальнейшего сопоставления в этом случае. Затем мы пытаемся сопоставить что-то, что не может совпадать (в данном случае ^).

Если строка не содержит "hede", тогда вторая альтернатива, пустой подшаблон, успешно соответствует строке темы.

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

0 голосов
/ 26 марта 2019

^ ((?! hede).) * $ - элегантное решение, за исключением того, что оно использует символы, поэтому вы не сможете комбинировать его с другими критериями. Например, скажем, вы хотели проверить отсутствие «хеде» и наличие «хаха». Это решение будет работать, потому что оно не будет использовать символы:

^ (?!. \ bhede \ b) (? =. \ bhaha \ b)

0 голосов
/ 09 июля 2018

С ConyEdit вы можете использовать командную строку cc.gl !/hede/, чтобы получить строки, не содержащие совпадения с регулярным выражением, или использовать командную строку cc.dl /hede/, чтобы удалить строки, содержащие совпадение с регулярным выражением. У них одинаковый результат.

0 голосов
/ 13 сентября 2016

Более простое решение - использовать не оператор !

Ваш , если оператор должен будет соответствовать "содержит", а не соответствовать "исключает".

var contains = /abc/;
var excludes =/hede/;

if(string.match(contains) && !(string.match(excludes))){  //proceed...

Я полагаю, что разработчики RegEx предполагали использование не операторов.

...