了解 CultureInvariant 和 IgnoreCase 在 [A-Za-z] 上的后果

本文关键字:后果 A-Za-z CultureInvariant IgnoreCase 了解 | 更新日期: 2023-09-27 18:32:39

如果我基于以下模式创建一个Regex@"[A-Za-z]+",如果我已经在使用RegOptions.CultureInvariant,它匹配的集合是否会通过添加RegOptions.IgnoreCase而改变(由于这样的问题(? 我认为这是一个明显的"不,这只是多余和重复的"。 在我的测试中,这就是我所展示的,但我想知道我是否由于确认偏见而错过了一些东西。

如果我在这一点上错了,请纠正我,但我相信我肯定需要使用CultureInvariant,因为我也不知道文化会是什么。 MSDN 参考

注意:这不是我需要使用的实际模式,只是其中最简单的关键部分。 完整的模式是:@"[A-Za-z0-9's!''#$(),.:;=@''-{}|/&]+",以防在符号、大小写和文化周围确实存在一些奇怪的行为。 不,我没有创建模式,我只是在消费它,无法更改它,我意识到在/&之前不需要|

如果我能改变模式...

  1. 具有CultureInvariantIgnoreCase的模式"[a-z]"在功能上等同于仅使用 "[A-Za-z]" CultureInvariant对吗?
  2. 假设#1是正确的,哪个会更有效,为什么? 我猜较短的模式评估更有效,但我不知道内部现在如何工作,以充满信心地说出来。

了解 CultureInvariant 和 IgnoreCase 在 [A-Za-z] 上的后果

使用此程序,我们可以测试所有可能的双字母序列:

static void Main()
{
    var defaultRegexOptions = RegexOptions.CultureInvariant | RegexOptions.ExplicitCapture | RegexOptions.Singleline;
    var regex1 = new Regex(@"^[A-Za-z]+$", defaultRegexOptions);
    var regex2 = new Regex(@"^[A-Za-z]+$", defaultRegexOptions | RegexOptions.IgnoreCase);
    ParallelEnumerable.Range(char.MinValue, char.MaxValue - char.MinValue + 1)
        .ForAll(firstCharAsInt =>
        {
            var buffer = new char[2];
            buffer[0] = (char)firstCharAsInt;
            for (int i = char.MinValue; i <= char.MaxValue; i++)
            {
                buffer[1] = (char)i;
                var str = new string(buffer);
                if (regex1.IsMatch(str) != regex2.IsMatch(str))
                    Console.WriteLine("dfjkgnearjkgh");
            }
        });
}

较长的序列可能会有所不同,但我认为这不太可能。这是没有区别的有力证据。

该程序需要 20 分钟才能运行。

不幸的是,这个答案并没有提供任何关于为什么会这样的见解。

所以我对这一切的运作方式有一个根本性的误解。 我想这就是让我失望的原因...

Regex regex = new Regex("[A-Za-z]", RegexOptions.IgnoreCase);

。将返回false regex.IsMatch("ı"),但true regex.IsMatch("İ")。 如果我删除IgnoreCase它为两者返回false,如果我使用CultureInvariant(带或不带IgnoreCase(,无论如何它都会返回false,这基本上归结为斯科特张伯伦在他的评论中所说的。 谢谢斯科特。

最终,我希望"İ"和"ı"都被拒绝,而我只是在考虑CultureInvariant之前就通过IgnoreCase加入而让自己都改变了。 如果我删除IgnoreCase并添加CultureInvariant那么我可以保持模式不变,并使其与我想要的相匹配。

如果我能够将模式更改为仅"[A-Z]"那么我可以使用两个标志并且仍然可以获得所需的行为。 但是关于改变模式,哪个更有效的那一点只是好奇心。 我不想讨论讨论中可能出现的所有问题,以及我可以改变模式的所有方法。 我关心的是文化、不区分大小写和这两个RegexOptions

总而言之,我需要放弃IgnoreCase然后围绕文化的整个问题就消失了。 如果模式是a-zA-Z,并且我需要使用IgnoreCase来匹配上下,那么我也需要使用CultureInvariant