簡體   English   中英

使用正則表達式生成字符串而不是匹配它們

[英]Using Regex to generate Strings rather than match them

我正在編寫一個 Java 實用程序,它可以幫助我生成大量數據以進行性能測試。 能夠為字符串指定一個正則表達式,這樣我的生成器會吐出與此匹配的東西,這真是太酷了。 有什么東西已經烤好了我可以用來做這個嗎? 還是有一個圖書館可以讓我大部分時間到達那里?

謝謝

編輯:

關於這個問題的建議庫的完整列表:

  1. Xeger * - Java
  2. Generex * - Java
  3. Rgxgen -Java
  4. rxrdg - C#

* - 取決於dk.brics.automaton

編輯:正如評論中提到的,谷歌代碼中有一個庫可以實現這一點: https ://code.google.com/archive/p/xeger/

另請參閱Mifmif建議的https://github.com/mifmif/Generex

原始信息:

首先,使用足夠復雜的正則表達式,我相信這是不可能的。 但是你應該能夠為簡單的正則表達式組合一些東西。

如果您查看類 java.util.regex.Pattern 的源代碼,您會發現它使用 Node 實例的內部表示。 每個不同的模式組件都有自己的 Node 子類實現。 這些節點被組織成一棵樹。

通過生成遍歷這棵樹的訪問者,您應該能夠調用重載的生成器方法或某種將某些東西拼湊在一起的 Builder。

幫助原始海報為時已晚,但它可以幫助新人。 Generex是一個有用的 java 庫,它提供了許多使用正則表達式生成字符串的功能(隨機生成,根據其索引生成字符串,生成所有字符串......)。

例子 :

Generex generex = new Generex("[0-3]([a-c]|[e-g]{1,2})");

// generate the second String in lexicographical order that matches 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 0e 0e 0f 0fe 0f 0f 0g 0ge 0g 0g 1a 1b 1c 1e
// 1ee 1e 1e 1f 1fe 1f 1f 1g 1ge 1g 1g 2a 2b 2c 2e 2ee 2e 2e 2f 2fe 2f 2f 2g
// 2ge 2g 2g 3a 3b 3c 3e 3ee 3e 3e 3f 3fe 3f 3f 3g 3ge 3g 3g 1ee

// Generate random String
String randomStr = generex.random();
System.out.println(randomStr);// a random value from the previous String list

披露

這篇文章中提到的項目屬於回答(Mifmif)問題的用戶。 根據規則,這需要提出。

Xeger (Java)也能夠做到這一點:

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

這個問題真的很老,雖然這個問題對我來說是真實的。 我試過xegerGenerex ,但它們似乎不符合我的要求。 它們實際上無法處理某些正則表達式模式(如a{60000} )或其他模式(例如(A|B|C|D|E|F) ),它們只是不會產生所有可能的值。 由於我沒有找到任何其他合適的解決方案 - 我創建了自己的庫。

https://github.com/curious-odd-man/RgxGen

該庫可用於生成匹配和不匹配的字符串。

maven central 上也有可用的神器。

使用示例:

RgxGen rgxGen = new RgxGen(aRegex);                     // Create generator
String s = rgxGen.generate();                           // Generate new random value

我已經為此滾動了自己的庫(在 c# 中,但對於 Java 開發人員來說應該很容易理解)。

Rxrdg 最初是為了解決為現實項目創建測試數據的問題。 基本思想是利用現有的(正則表達式)驗證模式來創建符合這些模式的隨機數據。 這樣就創建了有效的隨機數據。

為簡單的正則表達式模式編寫解析器並不難。 使用抽象語法樹生成字符串應該更容易。

我在飛行中,剛剛看到一個問題:我寫了最簡單但效率低下且不完整的解決方案。 我希望它可以幫助您開始編寫自己的解析器:

public static void main(String[] args) {

    String line = "[A-Z0-9]{16}";
    String[] tokens = line.split(line);
    char[] pattern = new char[100];
    int i = 0;
    int len = tokens.length;
    String sep1 = "[{";
    StringTokenizer st = new StringTokenizer(line, sep1);

    while (st.hasMoreTokens()) {
        String token = st.nextToken();
        System.out.println(token);

        if (token.contains("]")) {
            char[] endStr = null;

            if (!token.endsWith("]")) {
                String[] subTokens = token.split("]");
                token = subTokens[0];

                if (!subTokens[1].equalsIgnoreCase("*")) {
                    endStr = subTokens[1].toCharArray();
                }
            }

            if (token.startsWith("^")) {
                String subStr = token.substring(1, token.length() - 1);
                char[] subChar = subStr.toCharArray();
                Set set = new HashSet<Character>();

                for (int p = 0; p < subChar.length; p++) {
                    set.add(subChar[p]);
                }

                int asci = 1;

                while (true) {
                    char newChar = (char) (subChar[0] + (asci++));

                    if (!set.contains(newChar)) {
                        pattern[i++] = newChar;
                        break;
                    }
                }
                if (endStr != null) {
                    for (int r = 0; r < endStr.length; r++) {
                        pattern[i++] = endStr[r];
                    }
                }

            } else {
                pattern[i++] = token.charAt(0);
            }
        } else if (token.contains("}")) {
            char[] endStr = null;

            if (!token.endsWith("}")) {
                String[] subTokens = token.split("}");
                token = subTokens[0];

                if (!subTokens[1].equalsIgnoreCase("*")) {
                    endStr = subTokens[1].toCharArray();
                }
            }

            int length = Integer.parseInt((new StringTokenizer(token, (",}"))).nextToken());
            char element = pattern[i - 1];

            for (int j = 0; j < length - 1; j++) {
                pattern[i++] = element;
            }

            if (endStr != null) {
                for (int r = 0; r < endStr.length; r++) {
                    pattern[i++] = endStr[r];
                }
            }
        } else {
            char[] temp = token.toCharArray();

            for (int q = 0; q < temp.length; q++) {
                pattern[i++] = temp[q];
            }
        }
    }

    String result = "";

    for (int j = 0; j < i; j++) {
        result += pattern[j];
    }

    System.out.print(result);
}

在 stackoverflow 播客 11 上:

斯波爾斯基:是的。 還有一個新產品,如果你不想使用團隊系統,我們在 Redgate 的朋友有一個名為 SQL 數據生成器的產品 [ http://www.red-gate.com/products/sql_data_generator/index.htm] . 它是 295 美元,它只是生成一些真實的測試數據。 它會在實際存在的城市列中生成真實的城市,然后當它生成這些城市時,它會讓狀態正確,而不是把狀態弄錯,或者將狀態放入德國城市之類的......你知道,它會生成非常逼真的數據。 我不太確定所有功能是什么。

這可能不是您想要的,但它可能是一個很好的起點,而不是創建您自己的。

我似乎在 google 中找不到任何東西,所以我建議通過將給定的正則表達式解析為最小的工作單元(\w、[xx]、\d 等)並編寫一些基本方法來支持來解決這個問題那些正則表達式短語。

因此,對於 \w 您將有一個方法 getRandomLetter() 返回任何隨機字母,並且您還將擁有 getRandomLetter(char startLetter, char endLetter) 它為您提供兩個值之間的隨機字母。

您必須編寫自己的解析器,就像 String::Random (Perl) 的作者所做的那樣。 事實上,他沒有在該模塊的任何地方使用正則表達式,這正是 perl-coders 所習慣的。

另一方面,也許您可​​以查看源代碼以獲取一些指示。


編輯:該死的,布萊爾以 15 秒的優勢擊敗了我。

我知道已經有一個公認的答案,但我一直在使用RedGate 的數據生成器(克雷格的答案中提到的那個),它對我拋出的所有內容都非常有效。 它很快,這讓我想使用相同的正則表達式來為這個東西吐出的注冊碼之類的東西生成真實數據。

它需要一個正則表達式,如:

[A-Z0-9]{3,3}-[A-Z0-9]{3,3}

它會生成大量獨特的代碼,例如:

LLK-32U

這是 RedGate 想出來的一些大秘密算法,我們都不走運,還是我們這些凡人實際上可以做的事情?

它遠不支持完整的 PCRE 正則表達式,但我編寫了以下 Ruby 方法來獲取類似正則表達式的字符串並對其產生變體。 (對於基於語言的驗證碼。)

# q = "(How (much|many)|What) is (the (value|result) of)? :num1 :op :num2?"
# values = { :num1=>42, :op=>"plus", :num2=>17 }
# 4.times{ puts q.variation( values ) }
# => What is 42 plus 17?
# => How many is the result of 42 plus 17?
# => What is the result of 42 plus 17?
# => How much is the value of 42 plus 17?
class String
  def variation( values={} )
    out = self.dup
    while out.gsub!( /\(([^())?]+)\)(\?)?/ ){
      ( $2 && ( rand > 0.5 ) ) ? '' : $1.split( '|' ).random
    }; end
    out.gsub!( /:(#{values.keys.join('|')})\b/ ){ values[$1.intern] }
    out.gsub!( /\s{2,}/, ' ' )
    out
  end
end

class Array
  def random
    self[ rand( self.length ) ]
  end
end

這個問題很老了,但我在自己的搜索中偶然發現了它,所以我將為可能正在用其他語言搜索相同功能的其他人提供幾個鏈接。

  • 這里有一個 Node.js 庫: https ://github.com/fent/randexp.js
  • 這里有一個 PHP 庫: https ://github.com/icomefromthenet/ReverseRegex
  • PHP faker 包包括一個“regexify”方法來完成這個: https ://packagist.org/packages/fzaninotto/faker

如果要生成“關鍵”字符串,您可能需要考慮:

EGRET http://elarson.pythonanywhere.com/生成覆蓋正則表達式的“邪惡”字符串

MUTREX http://cs.unibg.it/mutrex/通過正則表達式突變生成故障檢測字符串

兩者都是學術工具(我是后者的作者之一)並且工作得相當好。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM