在字符串中查找多个不连续的字符出现次数

4

请问能否帮我写一个正则表达式,用于检查一个字符串是否含有至少两个(最好是n个)不连续的大写(或小写)字母。如果n=2,则PassWord,PAssword或PASSWord都是有效的情况。

当我尝试使用/(?=([A-Z]{2,3}))/g时,它匹配了PassWOrd但没有匹配PassWord。

奇怪的是,它还匹配了PaSSWOrd。我认为{2,3}中的3实际上意味着不会匹配超过3个大写字符。为什么SSWO也匹配了呢?

我尝试了类似的变化,但没有一个适用于我(这并不奇怪,因为我对正则表达式不是很熟悉)。

这可以使用正则表达式完成吗?


你必须使用正则表达式吗? - pstrjds
1
根据您的描述,PAssword和PASSWord应该只算一个出现次数,因为所有大写字母都在一起。您能告诉我为什么会被计算为两个吗? - Michał Turczyn
1
如果 n=2,那么 PASSWord 应该是有效的吗?我怀疑。你说这个单词中只能有两个大写 ASCII 字母,但实际上有五个。 - Wiktor Stribiżew
你必须使用正则表达式吗? 不一定,但现在似乎是尝试并学习它的好时机。 - djurod
如果n=2,PASSWord是否有效?我怀疑。 是的,你是正确的。对于n=2,PASSWord不应该是有效的。 感谢您的回答,这正是我在寻找的。 - djurod
显示剩余2条评论
1个回答

6
(^[A-Z]{2}$) 正则表达式匹配仅包含两个大写ASCII字母的字符串(没有多也没有少)。

(?=([A-Z]{2,3})) 正则表达式匹配在字符串中任何位置出现的2到3个连续的大写ASCII字母。您想要匹配仅包含2到3个大写ASCII字母的字符串,不一定是连续的。

要匹配仅包含两个大写ASCII字母的字符串(没有多也没有少),请使用以下表达式:

^(?:[^A-Z]*[A-Z]){2}[^A-Z]*$

或者,如果您只允许整个字符串中包含ASCII字母:

^(?:[a-z]*[A-Z]){2}[a-z]*$

查看正则表达式演示

模式细节

  • ^ - 字符串开始
  • (?:[^A-Z]*[A-Z]){2} - 恰好出现两次的连续字符
    • [^A-Z]* - 除ASCII大写字母外的零个或多个字符
    • [A-Z] - 一个ASCII大写字母
  • [^A-Z]* - 除ASCII大写字母外的零个或多个字符
  • $ - 字符串结束。

在C#中使用

var strs = new List<string> { "PassWord", "PAssword", "PASSWord"};
var n = 2;
var pat = $@"^(?:[^A-Z]*[A-Z]){{{n}}}[^A-Z]*$";
foreach (var s in strs) {
    Console.WriteLine("{0}: {1}", s, Regex.IsMatch(s, pat));
}

结果:

PassWord: True
PAssword: True
PASSWord: False

点击在线演示查看。

请注意,如果你需要在一个字符串中要求包含两个大写ASCII字母,而其他字符可以是任意字符,并不需要使用正则表达式,可以使用LINQ:

var strs = new List<string> { "PassWord", "PAssword", "PASSWord"};
var n = 2;
foreach (var s in strs) {
    var res = s.Count(c => (c >= 65 && c <= 90));
    Console.WriteLine("{0}: {1}", s, res == 2);
}

请参见另一个演示.Count(c => (c >= 65 && c <= 90)) 部分将计算字符串中任何位置的大写ASCII字母数,res==2 将返回一个布尔结果,即数字是否等于2。它可以轻松地调整为数字范围检查。
如果需要Unicode兼容性,请用 .Where(Char.IsUpper) 替换 .Count(c => (c >= 65 && c <= 90))

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接