如何替换正则表达式中除最后一个重复的字母之外的所有字母?

时间:2012-05-14 21:19:30

标签: c# regex backreference

这是我想要在Regex中进行转换的表格:

From       To
================
CAT        CAT
EGG        EGG
A          A
Z          Z
AA         ZA
BB         ZB
ZZ         ZZ
AAA        ZZA
HHHHH      ZZZZH

换句话说,如果字符串是重复2次或更多次的相同字母,我想用Z替换所有字母最后一个字母。

我在这里被精神上阻止了。这是我到目前为止所提出的,它不起作用:

FIND:     ^(?<=\1*?)([A-Z])(?=\1+)$
REPLACE:  Z

我不确定是否可以在捕获组之前使用反向引用,但无论如何,用\1替换第一个.都无济于事。

我正在使用C#,所以我正在寻找.NET风格的正则表达式。我当然可以通过正常的字符串操作来做到这一点,但我有一个特定于业务案例的需要使用正则表达式。

3 个答案:

答案 0 :(得分:3)

有人订购了一些dark magic吗?

FIND:    \G([A-Z])(?=\1)
REPLACE: Z

\G将每个匹配EITHER锚定到字符串的开头,如\A,或者到前一个匹配结束的位置。换句话说,正则表达式中的([A-Z])总是尝试匹配下一个字符,并且由于前瞻 - (?=\1) - 您知道下一个字符与您刚刚替换的字符相同。

此外,你的自我回答中的正则表达式对我不起作用。 +没有做任何有用的事情(毕竟你只关心下一个角色),但它也没有伤害任何东西。让它对我有用的是删除$

更新:我没有发现字符串必须是两个或更多相同字符而没有别的的要求。这意味着+$都是必需的。在我的时候,我将解决字符串XXXXXIIIII应该保持不变的额外要求。瞧!

\G(?!\A(?:XXX?|III?)$)([A-Z])(?=\1+$)

答案 1 :(得分:2)

这是可能的,首先匹配你想要的角色,然后做前瞻和后瞻,包括那些而不是主表达中的锚点,因为你希望表达式逐个字符匹配。

([A-Z])(?<=^\1*)(?=\1+$)

但是,它不会非常高效,因为它会为每个角色走完整个字符串。

最好使用正则表达式来检测字符串是否由相同的字符组成,然后使用普通的字符串替换方法替换除Z之外的所有字符,或者创建一个Zs字符串的长度为例如,原始的减一,并附加原始的第一个字符。

答案 2 :(得分:0)

可能像匹配然后替换的东西可能有效。

string [] Samps = {  "CAT",  "EGG",  "A",  "Z",  "AA",  "BB",  "ZZ",  "AAA",  "HHHHH" };
foreach (var item in Samps)
{
    string line = item + "\t\t";
    line += Regex.Match(item, @"^([A-Z])\1+$").Success ?
            Regex.Replace(item, @".(?!$)", "Z") :
            item;
    Console.WriteLine(line);
}

输出

CAT             CAT
EGG             EGG
A               A
Z               Z
AA              ZA
BB              ZB
ZZ              ZZ
AAA             ZZA
HHHHH           ZZZZH