Я изучаю Perl и заметил довольно специфическую причуду - пытающийся соответствовать одному из нескольких regex условий в некоторое время результатах цикла в том цикле, продолжающемся для бесконечности:
#!/usr/bin/perl
my $hivar = "this or that";
while ($hivar =~ m/this/ig || $hivar =~ m/that/ig) {
print "$&\n";
}
Вывод этой программы:
this
that
that
that
that
[...]
Я задаюсь вопросом, почему это? Есть ли любые обходные решения, которые менее неуклюжи, чем это:
#!/usr/bin/perl
my $hivar = "this or that";
while ($hivar =~ m/this|that/ig) {
print "$&\n";
}
Это - упрощение реальной проблемы, с которой я встречаюсь, и в то время как я интересуюсь этим в практической точке зрения, я также хотел бы знать то, что закулисный инициировал это поведение. Это - вопрос, который, кажется, не очень совместим с Google.
Спасибо!
Tom
Дело в том, что существует скрытое значение, связанное с каждой строкой , а не с каждым совпадением , которое определяет, где совпадение / g
будет пытаться продолжить и доступен через pos ($ string)
. Что происходит:
pos ($ hivar)
равно 0, / this /
соответствует позиции 0 и сбрасывает pos ($ hivar)
на 4. Второе совпадение не выполняется, потому что оператор или уже верен. $ &
становится "этим" и печатается. pos ($ hivar)
равно 4, / this /
не соответствует, потому что нет «this» в позиции 4 или выше. Неудачное совпадение сбрасывает pos ($ hivar)
на 0. / that /
соответствует позиции 6 и сбрасывает pos ($ hivar)
на 10. $ &
становится "этим" и печатается. pos ($ hivar)
равно 10, / this /
не соответствует, потому что нет «this» в позиции 10 или выше. Неудачное совпадение сбрасывает pos ($ hivar)
на 0. / that /
соответствует позиции 6 и сбрасывает pos ($ hivar)
на 10. $ &
становится "этим" и печатается. и шаги 4 и 5 повторяются бесконечно.
Добавление флага регулярного выражения c
(который сообщает механизму не сбрасывать pos
при неудачном сопоставлении) решает проблему в примере кода, который вы предоставили, но может или не может быть идеальным решением более сложной проблемы.