#regex #perl
#регулярное выражение #perl
Вопрос:
У меня есть следующий список элементов измерения (неполный, на самом деле он намного длиннее):
Ktr_12345_180
Ktr_12345_160
Ktr_12345_1130
Kst_12345_180
Kst_12345_112
Kst_12345_120
Kst_12345_160
Моя цель — создать подмножество элементов в редакторе подмножеств Jedox 2019.1.
Подмножество должно включать все элементы, начинающиеся с префикса "Ktr_"
, но не имеющие суффикса _160
или _180
Я уже создал регулярное выражение (Ktr_) [0-9] (_180|_160)
, которое идентифицирует элементы, которые мне не нужны.
Теперь я должен инвертировать его. Насколько мне известно, нет встроенной функции для инвертирования регулярного выражения, верно?
Итак, я попытался сделать это, используя отрицательный прогноз: (Ktr_) [0-9] (?!(_180|_160))
Это вообще не работает. Я пробовал это в разных формах, но не достиг своей цели…
Я ожидаю, что регулярное выражение доставит нужные элементы. Вместо этого он просто показывает каждый элемент, имеющий "Ktr_"
в качестве префикса.
Ответ №1:
Проблема в том, что
является жадным только настолько, насколько оно обеспечивает соответствие всему шаблону; в [0-9]
нем совпадают не все следующие цифры, а только все такие, что остальные части шаблона также совпадают.
Захватите переменную часть шаблона ( [0-9]
) и распечатайте ее, чтобы увидеть
my @ary = qw(
Ktr_12345_180
Ktr_12345_160
Ktr_12345_1130
Kst_12345_180
);
for (@ary) {
say "got $1 in $_" if /(Ktr_[0-9] )(?!_180|_160)/;
}
и мы получаем
получил Ktr_1234 в Ktr_12345_180 получил Ktr_12345 в Ktr_12345_1130 получил Ktr_1234 в Ktr_12345_160
Сопоставление 1234
оставляет 5
для удовлетворения ожидаемого значения «not _180» следующим после 1234
.
Чтобы настроить это, нам нужны подробные данные, и вопрос, похоже, допускает две возможности
-
Если всегда есть
_
следующее, как следует из примеров данных, то просто включите_
перед началом просмотра/Ktr_[0-9] _(?!180|160)/
что теперь требует, чтобы все цифры были сопоставлены раньше
_
. Это также «обеспечивает соблюдение»_
там -
Если мы будем следовать тому, что говорится в тексте
все элементы, начинающиеся с префикса «Ktr_», но не имеющие суффикса _160 или _180
тогда может не быть ничего следующего
Ktr_12345
(например) или, по крайней мере, не_
В этом случае необходимо принудительно сопоставлять только все последовательные цифры
/Ktr_[0-9] (?!_180|_160)/
где дополнительный шаблон
Комментарии:
1. @ikegami Ах, но, конечно! Что-то меня беспокоит… Спасибо
Ответ №2:
Другой способ — сопоставить шаблон, а затем отрицать по сравнению с отрицательным внешним видом.
Попробуйте это
$ cat paul.txt
Ktr_12345_180
Ktr_12345_160
Ktr_12345_1130
Kst_12345_180
Kst_12345_112
Kst_12345_120
Kst_12345_160
$ perl -lne ' print if /(Ktr_). ?(?<!_180|_160)b/ ' paul.txt
Ktr_12345_1130
$ perl -lne ' print if /(Ktr_) [0-9] . ?(?<!_180|_160)b/ ' paul.txt
Ktr_12345_1130
$
Ответ №3:
Правильное регулярное выражение, которое вам нужно, это,
bKtr_[0-9] _(?!1[68]0b)[0-9] b
Здесь b
границы слов вокруг регулярного выражения гарантируют, что оно не даст частичного совпадения в более крупном тексте, и (?!1[68]0b)
это отрицательный прогноз, необходимый для отклонения строк, которые являются либо 160
, либо 180
, а остальная часть шаблона похожа на вашу. Кроме того, если вам не нужна группа, вам не нужно записывать первую часть как (Ktr_)
и также это позволит Ktr_
использовать ее целиком один или несколько раз, что, глядя на ваши образцы, кажется, вам нежелательным. Итак, я изменил его на простое Ktr_
только, но в случае, если это было допустимым и действительно необходимым, сохраните его, заменив Krt_
на (Ktr_)
Ответ №4:
Вы можете использовать притяжательный квантификатор с дополнительным,
чтобы гарантировать, что [0-9]
совпадет столько цифр, сколько присутствует, и не пытаться выполнить обратный поиск, если совпадение не удается.
(Ktr_) [0-9] (?!(_180|_160))
Притяжательные кванторы доступны начиная с Perl 5.10 или раньше с синтаксисом pattern)» rel=»nofollow noreferrer»>независимого подвыражения.