什么正则表达式可以从字符串中删除重复的项目?

时间:2010-07-22 14:16:10

标签: regex unique-values

给定由:分隔的标识符字符串,是否可以构造正则表达式以将唯一标识符提取到另一个字符串中,也用:分隔?

如何使用正则表达式实现此目的?我试过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 个答案:

答案 0 :(得分:9)

在支持无限重复内部的.NET中,你可以搜索

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

并用空字符串替换所有匹配项。

Perl(至少Perl 5)只支持固定长度的lookbehinds,所以你可以尝试以下(使用lookahead,结果略有不同):

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

如果用空字符串替换它,则将删除重复条目的所有先前重复; last 将保留。而不是

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:?):然后检查你是否可以在字符串中的前面某处匹配相同的标识符,可选地后面跟一个冒号。

答案 1 :(得分:2)

退房:http://www.regular-expressions.info/duplicatelines.html

在考虑任何正则表达式时始终是一个有用的网站。

答案 2 :(得分:1)

$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

答案 3 :(得分:0)

如果标识符已排序,您可以使用lookahead / lookbehind进行排序。如果它们不是,那么这超出了正则表达式的计算能力。现在,仅仅因为正式正则表达式不可能并不意味着如果你使用一些perl特定的正则表达式功能是不可能的,但如果你想保持你的正则表达式可移植,你需要用支持变量的语言来描述这个字符串。

答案 4 :(得分:0)

这是一个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代码。