为什么这个正则表达式会返回true?

3
为什么这个正则表达式会返回true?
Regex.IsMatch("العسكرية", "العسكري")

我谷歌了一下,没有任何结果。

3个回答

7
我怀疑你发布的内容实际上是颠倒的,较短的文本实际上是模式,而较长的输入是要匹配的输入。在这种情况下,如果模式匹配除了单词最后一个字母以外的所有内容,那么它将返回true。
为了澄清,العسكري是模式,العسكرية是输入。由于我会阿拉伯语,我可以告诉你后者确实是前者的部分匹配,因此如果值实际上被颠倒,结果将为true。如果您参考这个阿拉伯字母表,您可以看到字母 yā’(在表的底部)就是所讨论的同一个字母。它的外观取决于其在单词中出现的位置。在前一个单词中,它出现在结尾,在后一个单词中,它是倒数第二个字母。
当我从您的帖子中复制/粘贴时,值会颠倒,导致结果为true。为了更好地使用它,我们可以拆分这些单词,以便在两种情况下查看预期结果。
string first = "العسكري";
string second = "العسكرية";
Console.WriteLine(Regex.IsMatch(first, second)); // false
Console.WriteLine(Regex.IsMatch(second, first)); // true

我不熟悉阿拉伯语,但是对于这两个字符串,new CultureInfo("ar").CompareInfo.IsPrefixnew CultureInfo("ar").CompareInfo.IsSuffix都没有返回true - dtb
@dtb 奇怪的是,当我从 OP 的帖子中粘贴时,我得到了 true,尽管如我所说,这些值是相反的,只能得到部分匹配。 - Ahmad Mageed
@dtb,使用我的示例代码中的变量,我得到了true:new CultureInfo("ar").CompareInfo.IsPrefix(second, first) - 你明白吗? - Ahmad Mageed
是的,第一次复制字符串时肯定出了问题。好答案,+1。 - dtb
@dtb 字符串匹配不是文化问题。要么字符相同,要么不相同。 - tchrist
显示剩余4条评论

2

这是针对散文而非代码设计的文本渲染规则带来的有趣结果。

如上所写,你方法调用中的第一个参数是“العسكرية”,这个长参数在右侧进行呈现(*)。这个更长的参数是输入,而左侧呈现的较短的子字符串实际上是模式,因此匹配成功。

(*: 这假定你的浏览器知道如何进行从右到左的呈现。如果你将代码片段粘贴到不支持复杂文本布局的编辑器或控制台中,你将看到它的真实面貌...尽管阿拉伯语会变成断字。)

诀窍在于,引号和逗号等标点符号没有方向,因此可以根据周围环境从左到右或从右到左进行呈现。代码片段的逻辑顺序是:

>>>>>>>>>>>>>>>
               <<<<<<<<<<<<<<<<<<<
                                  >>
Regex.IsMatch("العسكرية", "العسكري")

(这具有更令人困惑的属性,即看似出现在每个单独参数周围的引号实际上并不存在。)
这对于可读混合语言的一段内容来说还算有些争议的意义,但对于代码而言却非常令人困惑!您可以通过插入具有从左到右方向性的字符来阻止它发生:
Regex.IsMatch("العسكرية", /* foo */ "العسكري")

这段代码在功能上与原始代码相同,但显示方式有很大不同。您可以观察到当您输入第一个拉丁字母时,参数的位置会交换。


1

看起來 Regex.IsMatch() 判斷的是 regex 在字串中是否有出現,而不是整個字串是否符合 regex(根據文件說明,它 "指示指定的正則表達式是否在指定的輸入字串中找到匹配項目。"). 按照文件,第一個參數是輸入,另一個是模式,但這裡似乎相反了。在這兩個字符串中,最後(最左邊)的字符看起來不同,但可能是由於連字渲染方式的原因。當以 UTF-8 字節形式傾銷時,這些字符串是:

d8 a7 d9 84 d8 b9 d8 b3 d9 83 d8 b1 d9 8a

并且

d8 a7 d9 84 d8 b9 d8 b3 d9 83 d8 b1 d9 8a d8 a9

因此,第一个实际上是另一个的子字符串,这可以解释匹配(它确实需要将参数顺序反转为文档所说的顺序)。


ICK!! 不要显示字节,要显示 Unicode 字符,例如 Regex.IsMatch("\x{627}\x{644}\x{639}\x{633}\x{643}\x{631}\x{64A}\x{629}", "\x{627}\x{644}\x{639}\x{633}\x{643}\x{631}\x{64A}") 或更好的方式是 `Regex.IsMatch("\N{ARABIC LETTER ALEF}\N{ARABIC LETTER LAM}\N{ARABIC LETTER AIN}\N{ARABIC LETTER SEEN}\N{ARABIC LETTER KAF}\N{ARABIC LETTER REH}\N{ARABIC LETTER YEH}\N{ARABIC LETTER TEH MARBUTA}", "\N{ARABIC LETTER ALEF}\N{ARABIC LETTER LAM}\N{ARABIC LETTER AIN}\N{ARABIC LETTER SEEN}\N{ARABIC LETTER KAF}\N{ARABIC LETTER REH}\N{ARABIC LETTER YEH}")。有简单的工具可以显示这些形式。 - tchrist

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