C# 为正则表达式生成所有匹配项

C# 为正则表达式生成所有匹配项,c#,regex,recursion,fare,C#,Regex,Recursion,Fare,对于用户选择,我想提供一个与给定正则表达式匹配的数字列表。正则表达式本身非常简单,它只能看起来像123[0-9][0-9]或[4-9]34.2 我发现法儿不知怎么做了这项工作。请参见以下示例: string pattern = "123[0-9][0-9]"; var xeger = new Xeger(pattern); var match = xeger.Generate(); //match is e.g. "12349" 不幸的是,Fare lib只给了我一个可能的匹配,但并不是字符串

对于用户选择,我想提供一个与给定正则表达式匹配的数字列表。正则表达式本身非常简单,它只能看起来像123[0-9][0-9]或[4-9]34.2

我发现法儿不知怎么做了这项工作。请参见以下示例:

string pattern = "123[0-9][0-9]";
var xeger = new Xeger(pattern);
var match = xeger.Generate(); //match is e.g. "12349"
不幸的是,Fare lib只给了我一个可能的匹配,但并不是字符串可以拥有的所有100个可能的组合


如果您认为在这种情况下正则表达式不是一个好主意,并且更愿意建议使用for循环实现来取代chars,那么我也会使用它,但目前我不知道如何使用它?也许递归函数更聪明?

我宁愿创建自己的实现,也不愿使用库。下面的代码实现了您想要实现的功能

 private static Regex regexRegex = new Regex("\\[(?<From>\\d)-(?<To>\\d)]", RegexOptions.Compiled);

    private static IEnumerable<string> GetStringsForRegex(string pattern)
    {
        var strings = Enumerable.Repeat("", 1);
        var lastIndex = 0;
        foreach (Match m in regexRegex.Matches(pattern))
        {
            if (m.Index > lastIndex)
            {
                var capturedLastIndex = lastIndex;
                strings = strings.Select(s => s + pattern.Substring(capturedLastIndex, m.Index - capturedLastIndex));
            }
            int from = int.Parse(m.Groups["From"].Value);
            int to = int.Parse(m.Groups["To"].Value);
            if (from > to)
            {
                throw new InvalidOperationException();
            }
            strings = strings.SelectMany(s => Enumerable.Range(from, to - from + 1), (s, i) => s + i.ToString());
            lastIndex = m.Index + m.Length;
        }
        if (lastIndex < pattern.Length)
        {
             var capturedLastIndex = lastIndex;
             strings = strings.Select(s => s + pattern.Substring(capturedLastIndex));
        }
        return strings;
    }
private static Regex Regex=new Regex(“\\[(?\\d)-(?\\d)]”,RegexOptions.Compiled);
私有静态IEnumerable GetStringsForegex(字符串模式)
{
变量字符串=可枚举。重复(“,1);
var lastIndex=0;
foreach(在regex.Matches(模式)中匹配m)
{
如果(m.Index>lastIndex)
{
var capturedLastIndex=最后一个索引;
strings=strings.Select(s=>s+pattern.Substring(capturedlastinex,m.Index-capturedlastinex));
}
int-from=int.Parse(m.Groups[“from”].Value);
int-to=int.Parse(m.Groups[“to”].Value);
如果(从>到)
{
抛出新的InvalidOperationException();
}
strings=strings.SelectMany(s=>Enumerable.Range(from,to-from+1),(s,i)=>s+i.ToString());
lastIndex=米指数+米长度;
}
if(lastIndexs+pattern.Substring(capturedlastinex));
}
返回字符串;
}
基本上,代码为regex模式构造了所有解决方案。它甚至按字母顺序计算它们


小心
capturedlastinex
变量。它是必需的,否则编译器将捕获lastIndex变量,从而导致不正确的结果

这是我的代码,现在正在为我工作。不太通用,仅适用于字符串中的两个可能表达式,但它可以工作;)

列表可能匹配=新列表();
string expression=“123?[3-9]”//这是一个示例
if(表达式.Contains(“?”)| |表达式.Contains(“[”))
{               
int count=expression.count(f=>f=='?');
count+=expression.count(f=>f='[');
如果(计数1)
{
pos2=pattern.IndexOf('[',pos1);
start2=Convert.ToInt32(模式[pos2+1].ToString());
end2=Convert.ToInt32(模式[pos2+3].ToString());
模式=模式。移除(位置1,“[0-9]”。长度);
模式=模式。移除(位置2,“[0-9]”。长度);
字符串复制=模式;

对于(int i=start1;i Sorry不适用于
getStringsforgex(@“1\d3[0-9][0-9]”)而言
Sorry,但不幸的是,对于pattern=“1234.”或“1234[0-9]”来说都不起作用@L.B嗯,您最初写道“它只能看起来像123[0-9][0-9]或[4-9]34.2”。没有提到
\d
。(你可以通过将
[0-9]
一样处理来添加
支持@RaymondChen我以前没有写过任何东西:)重读问题、评论和答案。是的,如果我替换。用[0-9]它几乎可以正常工作。如果模式是123[0-9][0-9],我会得到类似“240[0-9]00”的结果。你对
[0-9]有什么期望+
对不起,我不知道你的意思123[0-9][0-9]给出12300、1231012311等等,但是
[0-9]+
会产生无限的结果。如果你知道模式,并且像你的例子那样受到限制,你就不需要正则表达式。嵌套的两个循环足够
for(int i=0;i<10;i++){for(int j=0;j<10;j++){}
。我最初认为只拥有两个嵌套循环可能很容易,但如何才能清楚地做到这一点?困难是什么?
var list=(从可枚举中的I开始。范围(0,10)从可枚举中的j开始。范围(6,4)选择“1”+I+“3”+j+“5”)。ToList();
        List<string> possibleMatches = new List<string>();

        string expression = "123?[3-9]" //this is an example

        if (expression.Contains("?") || expression.Contains("["))
        {               
            int count = expression.Count(f => f == '?');
            count += expression.Count(f => f == '[');
            if (count <= 2)
            {
                string pattern = expression.Replace('*', '.').Replace('?', '.');
                pattern = pattern.Replace(".", "[0-9]"); 

                int pos1 = pattern.IndexOf('[');
                int start1 = Convert.ToInt32(pattern[pos1 + 1].ToString());
                int end1 = Convert.ToInt32(pattern[pos1 + 3].ToString());

                int pos2 = 0;
                int start2, end2 = 0;
                if (count > 1)
                {
                    pos2 = pattern.IndexOf('[', pos1);
                    start2 = Convert.ToInt32(pattern[pos2 + 1].ToString());
                    end2 = Convert.ToInt32(pattern[pos2 + 3].ToString());

                    pattern = pattern.Remove(pos1, "[0-9]".Length);
                    pattern = pattern.Remove(pos2, "[0-9]".Length);

                    string copy = pattern;
                    for (int i = start1; i <= end1; i++)
                    {
                        copy = pattern.Insert(pos1, i.ToString());
                        for (int y = start2; y <= end2; y++)
                        {
                            possibleMatches.Add(copy.Insert(pos2, y.ToString()));
                        }
                    }
                }
                else
                {
                    pattern = pattern.Remove(pos1, "[0-9]".Length);

                    for (int i = start1; i <= end1; i++)
                    {
                        possibleMatches.Add(pattern.Insert(pos1, i.ToString()));
                    }
                }
            }