Да, вы можете использовать негативную перспективу.Используя ваши обозначения, мы можем построить форму такого комбинированного регулярного выражения:
/(?!F)D/
Хотя есть нюансы.Давайте рассмотрим простой пример.
my $patternD = '^(\d\d\d\d | \w\w)$';
my $patternF = 'AA | 12';
Как видите, patternD соответствует строкам, состоящим из 4 цифр или двухсимвольных символов.PatternF соответствует либо AA
, либо 12
.Таким образом, следующий фрагмент выводит то, что мы ожидаем.
my $str = '1121';
print "patternD matches\n" if $str =~ /$patternD/x; # patternD matches
print "patternF matches\n" if $str =~ /$patternF/x; # patternF matches
Теперь давайте создадим объединенное регулярное выражение, используя наивный подход.
my $combined = "(?!($patternF))$patternD";
print "Combined regex matches\n" if $str =~ /$combined/x; # Combined regex matches?!
Упс, у нас ложный положительный результат!(помните, наше объединенное регулярное выражение должно совпадать тогда и только тогда, когда регулярное выражение D соответствует, а F нет, но это не так).Почему это?Ответ прост.Мы создали наше объединенное регулярное выражение так, что если D совпадает в некоторой позиции, то F может совпадать только из той же позиции.В этом случае D совпадает в начале $str
(альтернатива \d\d\d\d
), где ни AA
, ни 12
не могут совпадать.Решение простое, хотя.Мы должны дать F некоторую гибкость, добавив .*
перед ним.Окончательный результат:
my $combined = "(?!.*($patternF))$patternD";
Независимо от того, где D совпадает, у F есть шанс найти совпадение в любом месте строки.
Этот пример показывает, что то, чего вы хотите достичь, безусловно выполнимо, но вы не можете просто смешать два регулярных выражения, вам лучше сначала внимательно изучить окончательный результат.
HTH