Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/regex/20.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Regex 使用类正则表达式条件生成字符串_Regex_String_Delphi_Generator_Enumerator - Fatal编程技术网

Regex 使用类正则表达式条件生成字符串

Regex 使用类正则表达式条件生成字符串,regex,string,delphi,generator,enumerator,Regex,String,Delphi,Generator,Enumerator,我想知道实现满足以下二次思考要求的最佳字符串生成器类是否可行: 生成标准使用 枚举 计数属性 索引访问 我对正则表达式感到不舒服:我无法给出一段起始代码,但我只想到了一个简单的实现,它使用TList作为基类,并对“暴力”生成的字符串使用过滤器(Regex) 其他最佳选择是什么? 排序:先按长度排序(最短优先),然后按字典排序 生成中要使用的字符范围的规范:所有可打印字符或[A-Z]、[A-Z]、数字、特殊符号和最终空格(regex?)的任何可能组合 以给定的最小值/最大值为界的字符

我想知道实现满足以下二次思考要求的最佳字符串生成器类是否可行:


  • 生成标准使用
  • 枚举
  • 计数属性
  • 索引访问

我对正则表达式感到不舒服:我无法给出一段起始代码,但我只想到了一个简单的实现,它使用TList作为基类,并对“暴力”生成的字符串使用过滤器(Regex)

其他最佳选择是什么?


  • 排序:先按长度排序(最短优先),然后按字典排序
  • 生成中要使用的字符范围的规范:所有可打印字符或[A-Z]、[A-Z]、数字、特殊符号和最终空格(regex?)的任何可能组合
  • 以给定的最小值/最大值为界的字符串长度
  • 受边界约束的搜索空间:开始字符串可能进行筛选的结束字符串(regex?)

上次编辑

首先,我用regex-like而不是regex重新表述了标题

我正在考虑修改第一个要求,因为这是一个敞开的大门,可能导致无法执行的问题

我需要正确措辞的建议和帮助


第二个想法完成了。仍然可以提出改进建议。

老问题,但没有人回答,悬赏仍然有效,我已经准备好了解决方案,所以这里有一个可能的答案:

我曾经写过一篇这样的文章。然而,它在C++/Qt中(虽然我几乎所有的程序都是用Delphi编写的,但其中一个是用C++)不支持Unicode,并且没有顺序保证

其工作原理如下:

  • 全部?{}+*|()运算符被展开(达到最大限制),因此只保留字符类和反向引用

    e、 g.
    [a-c]+[a-c][a-c][a-c][a-c][a-c][a-c][a-c][a-c][a-c][a-c][a-c][a-c][a-c][a-c][a-c][a-c][a-c][a-c][a-c][a-c][a-c][a-c][a-c][a-c][a-c][a-c][a-c][a-c][a-c][a-c][a-c][a-c][a-c]成为
    [a-c][ttt][ttt][ttt][ttt][ttt][a-t][t][a-t][t][t][a-c][a-c][t][a-

    (后一个表达式中的|只是表示法,程序在列表中保留每个备选子类)

  • 对多个字符的反向引用将替换为对单个字符的反向引用

    e、 g.上述表达式变为
    [a-c][a-c][a-c][a-c][a-c][a-c][a-c][a-c][a-c][a-c][a-c]|t | tt | tt | ttt |([x-z])foo\1\2 | at | au | bt bu

    现在,每个备选子项匹配一个固定长度的字符串

  • 对于每个备选方案,将打印从类中拾取字符的所有组合:

    e、 g.上述表达式变为
    a | b | c | aa | ba | cc | aaa | ccc | aaaa | cccc | t | tt | ttt | xxfoox | yxfooyx | zzfoozz at | au | bt code>

  • 您可能可以添加shortlex订单担保,如下所示:

  • 按字母顺序对类中的字符进行排序

  • 对步骤2中获得的备选方案进行排序。以上为长度

    (可选项的数量是指数级的,但与结果字符串的数量相比,它们的数量通常可以忽略不计)

  • 对字符类和反向引用进行排序/交换,以便每个引用都指向反向

  • 如前所述,枚举单个固定长度备选方案的可能字符串,但从最后一个字符类开始,而不是从第一个字符类开始,以获得字母顺序

    (如果有任何指向前方的反向参考,这将不起作用)

  • 如果有多个相同长度的可选项,请“并行”枚举它们,比较它们的当前字符串,并按字母顺序打印最小值。(即,合并每个备选方案的已排序列表。)

    这可以优化,例如,通过检测后缀中的不同前缀和安全字符类,可以在不影响排序的情况下枚举这些前缀和安全字符类。(例如,a[a-z]| b[a-z]有不同的前缀,[a-z]可以在不进行任何比较的情况下枚举)


  • 我会通过构造语言的最小值来实现这一点。如果您从正则表达式开始,这可以通过Thompson构造自动完成,然后是子集构造和最小化。例如,见

    有了DFA,您可以使用如下算法:

    Let P = { < START, [""] > } be a set of pairs <State, list of strings>
    for n = 0, 1, ... Max
      Let P' = {} be a new set 
      while P is not empty 
        Remove the pair <s, L> from P 
        For each transition s -- c --> t in alpha order of c
          if t is an accepting state,
              output l + c for each string l in L
          put <t, L + c> in P' (** i.e. append c to each string in L)
      end
      Set P = P'
    end
    

    由于不熟悉德尔菲,我只能从一个总体的观点来发言。在我看来,最好的方法是将正则表达式解析成一个表示其等价状态机的图(维基百科应该能够为您指出正确的方向)。从那里,可以通过对所述图形执行深度优先遍历来生成单词(当然要记住,它很可能是循环的)。这里的缺点是我们不能利用内置于regex支持的语言。+1:非常有趣。这是一种真正的生成方法,与我高度低效的生成器/测试方法相反。在我看来,这根本没有坏处:内置的regex支持用于评估,这会误导我设计解决方案。你可以考虑迁移你的评论作为答案,我觉得它是可以接受的。谢谢。这似乎是一种使用正则表达式的愚蠢方式。我认为生成生成器对象的简化生成器表达式系统可能有点类似于某些正则表达式功能(支持
    [a-Z]。
    [a-Z]*
    (在固定限制内)单独使用就足够了。通配符确实为生成字符串提供了一个有趣的问题。例如,第一个字符串是什么(按字典顺序排列)这可以由<代码> A*B<代码>产生吗?考虑<代码> AB <代码>之前>代码> B<代码>,<代码> AAB <代码> >代码> Ab>代码>等。我们可以归纳出第一个字符串是一个无限重复的<代码> A<代码>,后面是一个单一的<代码> B<代码>。显然我们不能表示这一点,因此我们必须设置一个固定的。(即任意)l
    import java.util.Comparator;
    import java.util.TreeSet;
    
    public class Test{
    
        public static class DFA {
    
            public static class Transition  {
    
                final int to;
                final char lo, hi; // Character range.
    
                public Transition(int to, char lo, char hi) {
                    this.to = to;
                    this.lo = lo;
                    this.hi = hi;
                }
    
                public Transition(int to, char ch) {
                    this(to, ch, ch);
                }
            }
    
            // transitions[i] is a vector of transitions from state i.
            final Transition [] [] transitions;
    
            // accepting[i] is true iff state i is accepting
            final boolean [] accepting;
    
            // Make a fresh immutable DFA.
            public DFA(Transition [] [] transitions, boolean [] accepting) {
                this.transitions = transitions;
                this.accepting = accepting;
            }
    
            // A pair is a DFA state number and the input string read to get there.
            private static class Pair {
                final int at;
                final String s;
    
                Pair(int at, String s) {
                    this.at = at;
                    this.s = s;
                }
            }
    
            // Compare pairs ignoring `at` states, since 
            // they are equal iff the strings are equal.
            private Comparator<Pair> emitOrder = new Comparator<Pair>() {
                @Override
                public int compare(Pair a, Pair b) {
                    return a.s.compareTo(b.s);
                }
            };
    
            // Emit all strings accepted by the DFA of given max length.
            // Output is in sorted order.
            void emit(int maxLength) {
                TreeSet<Pair> pairs = new TreeSet<Pair>(emitOrder);
                pairs.add(new Pair(0, ""));
                for (int len = 0; len <= maxLength; ++len) {
                    TreeSet<Pair> newPairs = new TreeSet<Pair>(emitOrder);
                    while (!pairs.isEmpty()) {
                        Pair pair = pairs.pollFirst();
                        for (Transition x : transitions[pair.at]) {
                            for (char ch = x.lo; ch <= x.hi; ch++) {
                                String s = pair.s + ch;
                                if (newPairs.add(new Pair(x.to, s)) && accepting[x.to]) {
                                    System.out.println(s);
                                }
                            }
                        }
                    }
                    pairs = newPairs;
                }
            }
        }
    
        // Emit with a little DFA for floating point numbers.
        public void run() {
            DFA.Transition [] [] transitions = {
                {   // From 0
                    new DFA.Transition(1, '-'),
                    new DFA.Transition(2, '.'),
                    new DFA.Transition(3, '0', '1'),
                },
                {   // From 1
                    new DFA.Transition(2, '.'),
                    new DFA.Transition(3, '0', '1'),
                },
                {   // From 2
                    new DFA.Transition(4, '0', '1'),
                },
                {   // From 3
                    new DFA.Transition(3, '0', '1'),
                    new DFA.Transition(4, '.'),
                },
                {   // From 4
                    new DFA.Transition(4, '0', '1'),
                }  
            };
            boolean [] accepting = { false, false, false, true, true };
            new DFA(transitions, accepting).emit(4);
        }
    
        public static void main (String [] args) {
            new Test().run();
        }
    }