用于验证姓名和姓氏的正则表达式?

时间:2009-05-20 16:05:26

标签: regex c# globalization

虽然这似乎是一个微不足道的问题,但我确信它不是:)

我需要验证来自世界各地的人的姓名和姓氏。我怎么能用正则表达式做到这一点?如果只是英国人,我认为这会削减它:

^[a-z -']+$

但是,我还需要支持这些案例:

  • 其他标点符号,因为它们可能会在不同的国家/地区使用(不知道哪个,但也许你这样做!)
  • 不同的Unicode字母集(重音字母,希腊语,日语,中文等)
  • 没有数字或符号或不必要的标点符号或符文等。

是否有一种标准方法可以验证我可以实施的这些字段,以确保我们的网站访问者拥有良好的体验,并且在注册时可以使用他们的名字

我会寻找类似于谷歌上可以找到的许多“电子邮件地址”正则表达式。

13 个答案:

答案 0 :(得分:41)

我其实不会打扰。

无论你想出什么正则表达式,我都可以在世界某个地方找到一个可以打破它的名字。

话虽如此,您确实需要清理输入,以避免Little Bobby Tables问题。

答案 1 :(得分:18)

我会尝试自己给出正确答案:

名称中唯一允许使用的标点是句号,撇号和连字符。我没有在角落案件清单中看到任何其他案例。

关于数字,只有一个案例有8个。我想我可以放心地禁止它。

关于信件,任何信件都有效。

我也想要包括空间。

这将归结为这个正则表达式:

^[\p{L} \.'\-]+$

这提出了一个问题,即撇号可以用作攻击向量。它应该被编码。

因此验证码应该是这样的(未经测试):

var name = nameParam.Trim();
if (!Regex.IsMatch(name, "^[\p{L} \.\-]+$")) 
    throw new ArgumentException("nameParam");
name = name.Replace("'", "'");  //' does not work in IE

有人能想到名称不应该通过此测试或可以通过的XSS或SQL注入的原因吗?


完整的测试解决方案

using System;
using System.Text.RegularExpressions;

namespace test
{
    class MainClass
    {
        public static void Main(string[] args)
        {
            var names = new string[]{"Hello World", 
                "John",
                "João",
                "タロウ",
                "やまだ",
                "山田",
                "先生",
                "мыхаыл",
                "Θεοκλεια",
                "आकाङ्क्षा",
                "علاء الدين",
                "אַבְרָהָם",
                "മലയാളം",
                "상",
                "D'Addario",
                "John-Doe",
                "P.A.M.",
                "' --",
                "<xss>",
                "\""
            };
            foreach (var nameParam in names)
            {
                Console.Write(nameParam+" ");
                var name = nameParam.Trim();
                if (!Regex.IsMatch(name, @"^[\p{L}\p{M}' \.\-]+$"))
                {
                    Console.WriteLine("fail");
                    continue;
                }
                name = name.Replace("'", "&#39;");
                Console.WriteLine(name);
            }
        }
    }
}

答案 2 :(得分:15)

我会允许所有内容(除了空字符串)并假设用户知道他的名字是什么。

有两种常见情况:

  1. 您关心的是该名称是否准确,并且是根据真实纸质护照或其他身份证明文件或信用卡进行验证。
  2. 你不在乎那么多,用户也可以注册为“Fred Smith”(或“Jane Doe”)。
  3. 如果是(1),您可以允许所有字符,因为您正在检查纸质文档。

    在情况(2)中,您也可以允许所有字符,因为“123 456”的假名并不比“Abc Def”更差。

答案 3 :(得分:10)

我认为你最好不要使用正则表达式排除你不想要的字符。试图获得每个变音,重音e,连字符等将是非常疯狂的。只是排除数字(但那么一个名为“George Forman the 4th”的人)和你知道你不想要的符号就像@#$%^或者你有什么。但即便如此,使用正则表达式只能保证输入与正则表达式匹配,它不会告诉你它是一个有效的名称

在澄清这是在试图阻止XSS后编辑: 名称字段上的正则表达式显然不会自行停止XSS。但是,本文有一个关于过滤的部分,如果你想走这条路,那么这是一个起点。

http://tldp.org/HOWTO/Secure-Programs-HOWTO/cross-site-malicious-content.html

s/[\<\>\"\'\%\;\(\)\&\+]//g;

答案 4 :(得分:6)

我认为这不是一个好主意。即使你找到一个合适的正则表达式(可能使用Unicode字符属性),这也不会阻止用户输入像 John Doe Max Mustermann 这样的伪名称(甚至还有是一个有这个名字的人, Abcde Fghijk Ababa Bebebe

答案 5 :(得分:6)

顺便说一下,你打算只允许使用拉丁字母,还是打算尝试验证中文,阿拉伯语,印地语等?

正如其他人所说,甚至不尝试来做到这一点。退后一步,问问自己你实际想要完成什么。然后尝试完成它,而不做任何关于人们姓名或者他们的意思的假设。

答案 6 :(得分:6)

您可以使用以下正则表达式代码验证由空格分隔的2个名称,并使用以下正则表达式代码:

^ [A-Za-zÀ-ú] + [A-Za-zÀ-ú] + $

或只是使用:

[[:lower:]] = [a-zà-ú]

[[:upper:]] = [A-ZÀ-Ú]

[[:alpha:]] = [A-Za-zÀ-ú]

[[:alnum:]] = [A-Za-zÀ-ú0-9]

答案 7 :(得分:2)

由于可能的所有角落情况,验证名称之类的东西是一个非常困难的问题。

转角案例

清理输入并让他们输入他们想要的任何名称,因为决定什么是有效名称和什么不是可能超出你正在做的范围;鉴于潜在的奇怪范围 - 合法的名称几乎是无限的。

如果他们想称自己为Tricyclopltz ^ 2-Glockenschpiel,那就是他们的问题,而不是你的问题。

答案 8 :(得分:2)

一个非常有争议的话题,我似乎在这里偶然发现了。然而,有时候在通行证上亲爱的小桌子并将小罗伯特连同他的分号和SQL注释行送到校长办公室是很好的。

VB.NET中的这个REGEX包括常规字母字符和各种欧洲字符。然而,可怜的老詹姆斯·麦克里斯坦 - 史密斯三世将不得不输入他的血统作为吉姆三世。

<asp:RegularExpressionValidator ID="RegExValid1" Runat="server"
                    ErrorMessage="ERROR: Please enter a valid surname<br/>" SetFocusOnError="true" Display="Dynamic"
                    ControlToValidate="txtSurname" ValidationGroup="MandatoryContent"
                    ValidationExpression="^[A-Za-z'\-\p{L}\p{Zs}\p{Lu}\p{Ll}\']+$">

答案 9 :(得分:0)

步骤:

  1. 首先删除所有重音
  2. 应用正则表达式
  3. 去除重音:

    private static string RemoveAccents(string s)
    {
        s = s.Normalize(NormalizationForm.FormD);
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < s.Length; i++)
        {
            if (CharUnicodeInfo.GetUnicodeCategory(s[i]) != UnicodeCategory.NonSpacingMark) sb.Append(s[i]);
        }
        return sb.ToString();
    }
    

答案 10 :(得分:0)

此代码对我来说非常适合JavaScript ^ [a-zA-Z] + [\ s |-]?[a-zA-Z] + [\ s |-]?[a-zA-Z] + $

这是方法:

function isVallidName(name) {
    var found = name.search(/^[a-zA-Z]+[\s|-]?[a-zA-Z]+[\s|-]?[a-zA-Z]+$/);
    if(found > -1) {
        return true;
    }
    else {
        return false;
    }
}

答案 11 :(得分:-1)

这有点帮助:

^[a-zA-Z]'?([a-zA-Z]|\.| |-)+$

答案 12 :(得分:-2)

这个应该有效 ^([A-Z]{1}+[a-z\-\.\']*+[\s]?)* 如果需要,可以添加一些特殊字符。