【问题标题】:Find string to regular expression programmatically?以编程方式查找字符串到正则表达式?
【发布时间】:2018-02-22 23:44:43
【问题描述】:

给定一个正则表达式,是否可以通过编程方式找到与该表达式匹配的字符串?如果是这样,请提及一个算法,假设存在一个字符串。

额外问题:如果可以,请给出该算法的性能/复杂性。


PS:注意我不是在问这个:Programmatically derive a regular expression from a string。我更有可能是在问储备问题。

【问题讨论】:

  • 据我所知,您正在寻找使用给定字符串组合生成正则表达式的算法?是你要找的吗?
  • 不@Simmant,给定一个正则表达式,我想要一个与该表达式匹配的字符串。
  • 好吧,如果我没记错的话,它更像是搜索算法。

标签: regex string algorithm performance time-complexity


【解决方案1】:

在字符串中找到符合该条件的给定表达式,为此我尝试了以下算法。

i) Create the array for all strings available in given source.

ii) Create a function with parameters for array, expression and initial index count.

iii) Call function recursively and increase the index with every move, until we match string has not found.

iv) Return/break the function if String with desired expression is found.

下面是相同的java代码:

public class ExpressionAlgo {

    public static void main(String[] args) {
        // TODO Auto-generated method stub

        String data = "A quantifier defines how often an element can occur. The symbols ?, *, + and {} define the quantity of the regular expressions";
        regCheck(data.split(" "), "sym", 0); 
    }

    public static void regCheck(String[] ar, String expresion, int i) {
               if(ar[i].contains(expresion)){
                   System.out.println(ar[i]);
                   return;
               }

               if(i<ar.length-1){
                   i=i+1;
                   regCheck(ar, expresion, i);
               }
    }
}

据我计算,这段代码的复杂度是 N^3,因为我使用了 split、contains 方法并递归调用 regCheck 方法。

【讨论】:

    【解决方案2】:

    假设您这样定义正则表达式:

    R :=
       <literal string>
       (RR)    -- concatenation
       (R*)    -- kleene star
       (R|R)   -- choice
    

    然后你可以定义一个递归函数S(r),它会找到一个匹配的字符串:

    S(<literal string>) = <literal string>
    S(rs) = S(r) + S(s)
    S(r*) = ""
    S(r|s) = S(r)
    

    例如:S(a*(b|c)) = S(a*) + S(b|c) = "" + S(b) = "" + "b" = "b"

    如果您有更复杂的正则表达式概念,您可以根据基本原语重写它,然后应用上述内容。例如,R+ = RR*[abc] = (a|b|c)

    请注意,如果您有一个已解析的正则表达式(因此您知道它的语法树),那么上述算法在正则表达式的大小上最多需要线性时间(假设您小心地执行字符串连接有效)。

    【讨论】:

    • 保罗谢谢!所以你的意思是时间复杂度可以是O(r),其中r是正则表达式的大小。对吧?
    • 是的,线性时间。
    • 谢谢!我认为regex-crossword-solver 对你来说会是一个有趣的问题。
    【解决方案3】:

    Generex 是一个用于从正则表达式生成字符串的 Java 库。

    查看:https://github.com/mifmif/Generex

    这是演示库使用的示例 Java 代码:

    Generex generex = new Generex("[0-3]([a-c]|[e-g]{1,2})");
    
    // Generate random String
    String randomStr = generex.random();
    System.out.println(randomStr);// a random value from the previous String list
    
    // generate the second String in lexicographical order that match the given Regex.
    String secondString = generex.getMatchedString(2);
    System.out.println(secondString);// it print '0b'
    
    // Generate all String that matches the given Regex.
    List<String> matchedStrs = generex.getAllMatchedStrings();
    
    // Using Generex iterator
    Iterator iterator = generex.iterator();
    while (iterator.hasNext()) {
        System.out.print(iterator.next() + " ");
    }
    // it prints:
    // 0a 0b 0c 0e 0ee 0ef 0eg 0f 0fe 0ff 0fg 0g 0ge 0gf 0gg
    // 1a 1b 1c 1e 1ee 1ef 1eg 1f 1fe 1ff 1fg 1g 1ge 1gf 1gg
    // 2a 2b 2c 2e 2ee 2ef 2eg 2f 2fe 2ff 2fg 2g 2ge 2gf 2gg
    // 3a 3b 3c 3e 3ee 3ef 3eg 3f 3fe 3ff 3fg 3g 3ge 3gf 3gg
    

    另一个:https://code.google.com/archive/p/xeger/

    这是演示库使用的示例 Java 代码:

    String regex = "[ab]{4,6}c"; 
    Xeger generator = new Xeger(regex); 
    String result = generator.generate(); 
    assert result.matches(regex);
    

    【讨论】:

    • 酷!知道这个库使用的算法的复杂性吗?
    • 它使用 dk.brics.automaton。详情可以参考cs.au.dk/~amoeller/automaton
    • 如果生成的字符串用于令牌或 id,它可能会受到攻击,所有递归迭代的组合是否保持相同??
    • @DucFilan 我在任何一个链接中都找不到任何复杂性线索。你可以吗?
    猜你喜欢
    • 1970-01-01
    • 2021-09-15
    • 1970-01-01
    • 2016-05-16
    • 2012-05-12
    • 1970-01-01
    • 2012-04-25
    • 2022-01-20
    相关资源
    最近更新 更多