c#根据模式生成随机字符串

时间:2013-01-18 10:03:35

标签: c# regex

我正在尝试根据模式进行简单的字符串生成 我的想法是使用Regex进行简单的替换。 我从简单的方法开始:

private static string parseTemplate(string template)
{
    return Regex.Replace(template, @"(\[d)((:)?([\d]+)?)\]", RandomDigit());
}

private static string RandomDigit()
{
    Random r = new Random();
    return r.Next(0, 9).ToString();
}

现在做的是将[d][d:3]等组替换为应该是随机数字的组。
不幸的是,每个组都被替换为相同的数字,例如,如果我放test [d][d][d:3]我的方法将返回test 222
我想在每个地方获得不同的数字,例如test 361

我遇到的第二个问题是如何处理长度:

现在我必须为我想要的每个数字指定[d],但指定[d:3]并获得相同的输出会更容易。

我知道有一个名为Fare的项目,但我想在没有此库的情况下执行此操作

现在我只搜索[d],但此方法是否正常可以添加其他组,例如:[s]特殊字符或任何其他类型的图案都没有问题

EDIT1

有人建议我将Random更改为静态变量,如下所示:

private static string parseTemplate(string template)
    {
        return Regex.Replace(template, @"(\[d)((:)?([\d]+)?)\]", RandomDigit());
    }

    private static Random r = new Random();

    private static string RandomDigit()
    {
        return r.Next(0, 9).ToString();
    }

问题在于,当我这样调用我的代码时:

Console.WriteLine(parseTemplate("test [d:2][d:][d]"));
Console.WriteLine(parseTemplate("test [d:2][d:][d]")); 

我得到像这样的输出

test 222
test 555

我想输出这样的(例如):

test 265
test 962

我认为问题出在Regex.Replace上,只调用RandomDigit一次。

3 个答案:

答案 0 :(得分:3)

关于你的第一个问题:当你调用new Random()时,每次调用函数时都会播放相同的值 - 初始化静态Random成员变量一次然后返回r.Next(0,9).ToString();

编辑:

在回答您的评论时,请尝试将MatchEvaluator与委托一起使用,如下所示(未经测试):

static string RandomReplacer(Match m)
{
    var result = new StringBuilder();
    foreach (char c in m.ToString())
        result.Append(c == 'd' ? RandomDigit() : c);
    return result.ToString()
}

private static string parseTemplate(string template)
{
    return Regex.Replace(template, @"(\[d)((:)?([\d]+)?)\]", new MatchEvaluator(RandomReplacer));
}

然后,您可以扩展此方法以匹配[d:3],并相应地在您的MatchEvaluator中解析它,解决您的第二个问题。

答案 1 :(得分:1)

Assumnig [d:3]表示“三个随机数字”,以下MatchEvaluator使用长度(从第4组读取)生成随机数字字符串:

static string ReplaceSingleMatch(Match m)
{
    int length;
    if (!int.TryParse(m.Groups[1].Value, out length))
        length = 1;
    char[] chars = new char[length];
    for (int i = 0; i < chars.Length; i++)
        chars[i] = RandomDigit()[0];
    return new string(chars);
}

然后您可以按如下方式调用它:

private static string parseTemplate(string template)
{
    return Regex.Replace(template, @"\[d(?::(\d+))?\]", ReplaceSingleMatch);
}

您可能希望更改RandomDigit以返回单个char而不是字符串,或者取int并返回多个字符。

答案 2 :(得分:1)

private static string GenerateMask(string mask)
{
    StringBuilder output = new StringBuilder();
    for (int i = 0; i < mask.Length; i++)
    {
        if (mask[i] == 'd' && mask[i - 1] != '\\')
        {
            int quantifier = 1;

            if (mask[i + 1] == ':')
                Int32.TryParse(mask[i + 2].ToString(), out quantifier);

            output.Append(GetRandomDigit(quantifier));
            i += 2;
        }
        else
        {
            if(mask[i] != '\\')
            output.Append(mask[i]);
        }
    }

    return output.ToString();
}

private static string GetRandomDigit(int length)
{
    Random random = new Random();
    StringBuilder output = new StringBuilder();
    while (output.Length != length)
        output.Append(random.Next(0, 9));
    return output.ToString();
}

有一个自定义算法,我只是为了好玩而放在一起,这里是实现:

Console.WriteLine(GenerateMask(@"Hey Da\d, meet my new girlfrien\d she's d:2"));
//Output: Hey Dad, meet my new girlfriend she's 44