Регулярное выражение Perl, удаляющее повторяющиеся последовательные подстроки в строке - PullRequest
4 голосов
/ 05 апреля 2011

Я попытался выполнить поиск по этой конкретной проблеме, но все, что я получаю, это либо удаление дублирующих строк, либо удаление повторяющихся строк, где они разделены разделителем.

Моя проблема немного другая.У меня есть строка, такая как

    "comp name1 comp name2 comp name2 comp name3" 

, где я хочу удалить повторное имя компа2 и вернуть только

    "comp name1 comp name2 comp name3" 

Это не последовательные повторяющиеся слова, а последовательные повторяющиеся подстроки.Есть ли способ решить эту проблему с помощью регулярных выражений?

Ответы [ 5 ]

7 голосов
/ 05 апреля 2011
s/(.*)\1/$1/g

Имейте в виду, что время выполнения этого регулярного выражения является квадратичным по длине строки.

3 голосов
/ 05 апреля 2011

Это работает для меня (MacOS X 10.6.7, Perl 5.13.4):

use strict;
use warnings;

my $input = "comp name1 comp name2 comp name2 comp name3" ;
my $output = "comp name1 comp name2 comp name3" ;

my $result = $input;
$result =~ s/(.*)\1/$1/g;

print "In:   <<$input>>\n";
print "Want: <<$output>>\n";
print "Got:  <<$result>>\n";

Ключевой точкой является '\ 1' в сопоставлении.

2 голосов
/ 05 марта 2013

Чтобы избежать удаления повторяющихся символов в , скобки (например, comm1 -> com1). * В регулярном выражении с \ b.

s/(\b.*\b)\1/$1/g
1 голос
/ 05 апреля 2011

Если вам нужно что-то, работающее за линейное время, вы можете split строку и выполнить итерацию по списку:

#!/usr/bin/perl                                                                                                                                                                                       

use strict;
use warnings;

my $str = "comp name1 comp name2 comp name2 comp name3";
my @elems = split("\\s", $str);
my $prevComp;
my $prevFlag = -1;
foreach my $elemIdx (0..(scalar @elems - 1)) {
    if ($elemIdx % 2 == 1) {
        if (defined $prevComp) {
            if ($prevComp ne $elems[$elemIdx]) {
                print " $elems[$elemIdx]";
                $prevFlag = 0;
            }
            else {
                $prevFlag = 1;
            }
        }
        else {
            print " $elems[$elemIdx]";
        }
        $prevComp = $elems[$elemIdx];
    }
    elsif ($prevFlag == -1) {
        print "$elems[$elemIdx]";
        $prevFlag = 0;
    }
    elsif ($prevFlag == 0) {
        print " $elems[$elemIdx]";
    }
}
print "\n";

Возможно, грязно, но должно работать быстрее.

1 голос
/ 05 апреля 2011

Я никогда не работаю с языками, которые поддерживают это, но так как вы используете Perl ...

Иди сюда .. и см. Этот раздел ....

Полезный пример: проверка на двойные слова

При редактировании текста легко закрадываются двойные слова, такие как "the". Используя regex \ b (\ w +) \ s + \ 1 \ b в текстовом редакторе, вы легко можете их найти. Чтобы удалить второе слово, просто введите \ 1 в качестве текста замены и нажмите кнопку Заменить.

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