Какое регулярное выражение может удалить повторяющиеся элементы из строки? - PullRequest
9 голосов
/ 22 июля 2010

Учитывая строку идентификаторов, разделенных :, возможно ли построить регулярное выражение для извлечения уникальных идентификаторов в другую строку, также разделенную :?

Как можно добиться этого с помощью регулярного выражения? Я попытался s/(:[^:])(.*)\1/$1$2/g безуспешно, потому что (.*) является жадным и пропускает до последнего матча $1.

Пример: a:b:c:d:c:c:x:c:c:e:e:f должен дать a:b:c:d:x:e:f

Примечание: я пишу на Perl, но я бы очень хотел использовать для этого регулярное выражение.

Ответы [ 5 ]

9 голосов
/ 22 июля 2010

В .NET, который поддерживает бесконечное повторение внутри вид сзади, вы можете искать

(?<=\b\1:.*)\b(\w+):?

и замените все совпадения пустой строкой.

Perl (по крайней мере, Perl 5) поддерживает только видоискатели фиксированной длины, поэтому вы можете попробовать следующее (используя просмотр, с немного отличным результатом):

\b(\w+):(?=.*\b\1:?)

Если вы замените это пустой строкой, все предыдущие повторения повторяющейся записи будут удалены; последний один останется. Так что вместо

a:b:c:d:x:e:f

вы бы получили

a:b:d:x:c:e:f

Если все в порядке, вы можете использовать

$subject =~ s/\b(\w+):(?=.*\b\1:?)//g;

Пояснение:

Первое регулярное выражение:

(?<=\b\1:.*): Проверьте, можете ли вы соответствовать содержанию обратной ссылки №. 1, за которым следует двоеточие, где-то в строке.

\b(\w+):?: сопоставить идентификатор (от границы слова до следующего :), за которым необязательно следует двоеточие.

Второе регулярное выражение:

\b(\w+):: сопоставить идентификатор и двоеточие.

(?=.*\b\1:?): Затем проверьте, можете ли вы сопоставить один и тот же идентификатор, за которым может следовать двоеточие, где-то впереди строки.

2 голосов
/ 22 июля 2010

Выезд: http://www.regular -expressions.info / duplicatelines.html

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

1 голос
/ 22 июля 2010
$str = q!a:b:c:d:c:c:x:c:c:e:e:f!;

1 while($str =~ s/(:[^:]+)(.*?)\1/$1$2/g);

say $str

вывод:

a:b:c:d:x:e:f
0 голосов
/ 22 июля 2010

вот версия awk, не нужно регулярное выражение.

$ echo "a:b:c:d:c:c:x:c:c:e:e:f" | awk -F":" '{for(i=1;i<=NF;i++)if($i in a){continue}else{a[$i];printf $i}}'
abcdxef

разделите поля на ":", пройдитесь по разделенным полям, сохраните элементы в массиве.проверить на наличие и, если существует, пропустить.Остальное распечатай.Вы можете легко перевести это на Perl-код.

0 голосов
/ 22 июля 2010

Если идентификаторы отсортированы, вы можете сделать это, используя lookahead / lookbehind. Если это не так, то это выходит за рамки вычислительных возможностей регулярного выражения. Теперь, просто потому, что это невозможно с формальным регулярным выражением, не означает, что это невозможно, если вы используете какую-то особенность регулярного выражения для perl, но если вы хотите сохранить регулярные выражения регулярными, вам нужно описать эту строку на языке, который поддерживает переменные.

...