繁体   English   中英

比较并验证两个字符串

[英]Compare and validate two strings

// A = Alphabetic, X = Alphanumeric, N = Numeric character

string strForMatching = "AAAAXXXX-NNNN-AA";

string[] strToBeValidated = new string[]
{
    "333TEST",
    "TEST4444-1234-AB",
    "ABCD12AB-1234-99",
    "ABCD2345-1234-AB",
    "PPP12AA-9876"
};

通过for循环,我将每个字符串从字符串数组传递给此方法

public bool ValidateString(string strForMatching, string strToBeValidated)
{
    bool isValid = false;

    // what to put here?

    return isValid;
}

我想验证strToBeValidatedstrForMatching

这意味着:

  • 333TEST无效
  • ABCD2345-1234-AB有效
  • PPP12AA-9876有效
  • PPPPP12AX-1234-AB无效。

有的值应该与strForMatching匹配。 我还需要验证分隔符。

我不能使用正则表达式,因为我有AAAAXXX-NNNN-AA ,在我的情况下,1到4个字母是可以的,但是有效,但对于X和N来说,超过4个字母是无效的,可以更改/ or # or @ ,可以是/ or # or @任何东西。 如果我将使用正则表达式,它将检查直到固定长度

此正则表达式似乎按预期工作

string[] strTobeValidate = new string[] {"333TEST", "TEST4444-1234-AB", "ABCD12AB-1234-99", "ABCD2345-1234-AB", "PPP12AA-9876" };
Regex r = new Regex(@"[A-Za-z]{4}[A-Za-z0-9]{4}-[0-9]{4}-[A-Za-z]{2}");
foreach(string s in strTobeValidate)
{
    Match m = r.Match(s);
    if(m.Success == false)
        Console.WriteLine("No match for: " + s);
    else
        Console.WriteLine(m.ToString());

}

含义:

  • 第一组四个字符{4}应该在AZ(大写)或az(小写)的范围内
  • 第二组四个字符应与以前相同,但也可以包含数字0-9
  • 减号将跟随
  • 第三组四个字符只是数字
  • 减号将跟随
  • 第四组2个字符只是字母字符

现在将Regex模式应用于输入字符串,您将发现仅第二和第四字符串匹配。

查看评论,我尝试构建一个简单的模式构建器。

string BuildPattern(string h)
{
    StringBuilder sb = new StringBuilder();
    string curPattern = "";
    char curChar = ' ';
    int cnt = 0;
    foreach(Char c in h)
    {
        if(c != curChar && cnt != 0)
        {
            sb.Append(curPattern);
            sb.Append("{" + cnt.ToString() + "}");
            cnt = 0;
            curPattern = "";
        }
        curChar = c;
        switch(c)
        {
            case 'A':
                curPattern = "[A-Za-z]";
                cnt++;
                break;
            case 'X':
                curPattern = "[A-Za-z0-9]";
                cnt++;
                break;
            case 'N':
                curPattern = "[0-9]";
                cnt++;
                break;
            default:
                sb.Append(c);
                break;
        }
    }
    sb.Append(curPattern);
    sb.Append("{" + cnt.ToString() + "}");
    return sb.ToString();
}

并用此代码更改准备Regex模式的代码:

string strForMatching = "AAAANNAA-NNNN-NN";
string pattern = BuildPattern(strForMatching);
// Fixed -> Regex r = new Regex(@"[A-Za-z]{4}[A-Za-z0-9]{4}-[0-9]{4}-[A-Za-z]{2}");
// Dynamic pattern 
Regex r = new Regex(pattern);

但是,这需要进行更广泛的测试……

如果您希望它是动态构建的,那么我将完全避免使用正则表达式。 构建一些对象来为您完成工作。

首先是一个非常简单的类,仅用于通过任意匹配检查来验证单个字符:

public class Matcher
{
    public char Flag { get; private set; }
    private readonly Predicate<char> Checker;

    public Matcher(char flag, Predicate<char> checker)
    {
        this.Flag = flag;
        this.Checker = checker;
    }

    public bool DoesMatch(char character)
    {
        return Checker(character);
    }
}

然后是一些繁重的验证类:

public class StringValidator
{
    private Dictionary<char, Matcher> Matchers = new Dictionary<char, Matcher>();

    public StringValidator()
    {
        Matchers = new[]{
            new Matcher('A', c => Char.IsLetter(c)),
            new Matcher('N', c => Char.IsDigit(c)),
            new Matcher('X', c => Char.IsLetter(c) || Char.IsDigit(c)),
            new Matcher('-', c => c == '-')}
            .ToDictionary(m => m.Flag);
    }

    public bool ValidateString(string strForMatching, string strTobeValidated)
    {
        if (strForMatching.Length != strTobeValidated.Length)
            return false;

        for(int i = 0; i < strTobeValidated.Length; i++)
        {
            Matcher matcher = GetMatcher(strForMatching[i]);

            if (!matcher.DoesMatch(strTobeValidated[i]))
                return false;
        }

        return true;
    }

    private Matcher GetMatcher(char flag)
    {
        Matcher matcher;

        if(!Matchers.TryGetValue(flag, out matcher))
            throw new IndexOutOfRangeException(String.Format("No matcher for character '{0}'", flag));

        return matcher;
    }
}

现在,您如何选择创建匹配的例程或组织它们,或者它们的标志由您决定。 在这种情况下, StringValidator的规则是“硬编码的”,但是您可以更改该规则以通过构造函数或通过公共方法进行更改。

另外,我使用的规则Char.IsLetterChar.IsDigit超出了简单的“ AZ”和“ 0-9”范围,但足以证明其工作原理。 如果需要,可以用正则表达式或其他支票随意替换那些特定的支票。

另外,您的示例规则/输出似乎不正确(例如,我希望“ PPP12AA-9876”与“ AAAAXXXX-NNNN-AA” 匹配)。 目前,这会检查长度是否匹配,但是您可以摆脱它。 而且,如果匹配模式比用于验证的输入短(反之亦然),我就表示不满意,因此我将根据您的确切要求将其留给您作为练习。

一些示例用法:

string[] stringsToValidate = new string[] { 
                                       "333TEST",
                                       "TEST4444-1234-AB",
                                       "ABCD12AB-1234-99",
                                       "ABCD2345-1234-AB",
                                       "PPP12AA-9876"
                                   };
string strForMatching = "AAAAXXXX-NNNN-AA";

var validator = new StringValidator();

foreach(var strToValidate in stringsToValidate)
{
    bool isValid = validator.ValidateString(strForMatching, strToValidate);
    Console.WriteLine(strToValidate + ": " + isValid);
}

输出:

333TEST:错误
TEST4444-1234-AB:是的
ABCD12AB-1234-99:错误
ABCD2345-1234-AB:是的
PPP12AA-9876:错误

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM