9

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

如何使用正则表达式来实现这一点?我试过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 进行编码,但我非常感谢为此使用正则表达式。

4

5 回答 5

10

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

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

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

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

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

于 2010-07-22T14:43:00.367 回答
2

查看:http ://www.regular-expressions.info/duplicatelines.html

在考虑任何正则表达式时总是一个有用的站点。

于 2010-07-22T14:18:05.730 回答
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
于 2010-07-22T14:42:14.660 回答
0

如果标识符已排序,您可以使用前瞻/后瞻来完成。如果不是,那么这超出了正则表达式的计算能力。现在,仅仅因为正式的正则表达式不可能,并不意味着如果您使用某些 perl 特定的正则表达式功能就不可能,但是如果您想让您的正则表达式保持可移植性,您需要用支持变量的语言来描述这个字符串。

于 2010-07-22T14:37:23.440 回答
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 代码。

于 2010-07-22T14:44:49.553 回答