Задание: есть текст, допустим abc/*de/*f*/m*/x с комментариями, которые нужно удалить регулярным выражением, причем, если в комментарии есть вложенный комментарий, то сначала надо удалить его.
У меня получилось что-то такое:
while ($string =~ m|/\*(.*?)\*/|) {
$string =~ s|(/\*((?!(.*?/\*).*?).*?)\*/.*?)|$_|;
print ""$string
;
}
Получим:
abc/*de/*f*/m*/x
abc/*dem*/x
abcx
И все вроде работает хорошо, но если в примере будут идти два комментария подряд, допустим теперь строка abc/*de/*f*/*/x, то программа зациклится.
Подскажите, как можно решить эту проблему.
Ответ
$string="abc/*def/*gh/*j*/ik*/lmn*/opq/*r/*st*/uvw*/xyz";
print "$string
";
while($string=~m|/\*.*?\*/|) { # До тех пор пока комментарии остались
$string=~s|/\*((?!.*?(?0)).*?)\*/||; # Вырезаем один
print "$string
";
}
Результат:
abc/*def/*gh/*j*/ik*/lmn*/opq/*r/*st*/uvw*/xyz
abc/*def/*gh/*j*/ik*/lmn*/opq/*ruvw*/xyz
abc/*def/*gh/*j*/ik*/lmn*/opqxyz
abc/*def/*ghik*/lmn*/opqxyz
abc/*deflmn*/opqxyz
abcopqxyz
Смысл вырезающей регулярки:
/\* # Комментарий открылся
( # Выделяющая группа
(?!.*?(?0)) # Внутри которой не содержится еще одно выражение
.*?
)
\*/ # Комментарий закрылся
Основа в ссылке (?0), которая на свое место подставляет текст всего выражения целиком, рекурсивно.
Комментариев нет:
Отправить комментарий