Хотите, чтобы подстановка регулярного выражения в perl начиналась заново и избегала трюка `1 while` - PullRequest
0 голосов
/ 30 ноября 2018

Пример: я хочу удалить дубликаты символов в $s, например так:

my $s = 'aabbbcbbac';
1 while $s =~ s/((.).*)\2/$1/;
print $s, "\n";                     #prints abc

Существует ли простой и короткий способ избежать трюка 1 while и удалить дубликаты всего одним s///g?Как заставить его «начать сначала»?с помощью \G или какого-то вида отставания | -ahead?Просто добавление /g не является решением здесь.

Ответы [ 3 ]

0 голосов
/ 30 ноября 2018

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

reverse строка, удалите символы, используя просмотрвперед и reverse снова

$t = reverse $s;
$t =~ s/(.)(?=.*\1)//sg;
$s = reverse $t;

Если у вас есть Perl 5.14 или выше и вы можете использовать модификатор /r для подстановок, вы получите

$s = reverse( reverse($s) =~ s/(.)(?=.*\1)//grs );
0 голосов
/ 02 декабря 2018

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

0 голосов
/ 30 ноября 2018

Решение для нерегулярных выражений может быть построено с использованием split, grep и join с поисковым хешем.Это, вероятно, не намного более читабельно, хотя.

my $s = 'aabbbcbbac';
my %seen;
$s = join '', grep { !$seen{$_}++ } split //, $s;
print $s, "\n";

Это выводит

abc
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...