मैच के बजाय स्ट्रिंग्स उत्पन्न करने के लिए रेगेक्स का उपयोग करना


108

मैं एक जावा उपयोगिता लिख ​​रहा हूं जो मुझे प्रदर्शन परीक्षण के लिए डेटा का भार उत्पन्न करने में मदद करता है। स्ट्रिंग्स के लिए रेगेक्स निर्दिष्ट करने में सक्षम होना वास्तव में अच्छा होगा ताकि मेरा जनरेटर उन चीजों से बाहर निकल जाए जो इस से मेल खाते हैं। वहाँ पहले से ही पके हुए कुछ है जो मैं यह करने के लिए उपयोग कर सकता हूं? या वहाँ एक पुस्तकालय है जो मुझे वहां सबसे ज्यादा मिलता है?

धन्यवाद


1
यहाँ एक उपयोगी जावा लाइब्रेरी है जो स्ट्रिंग को बनाने के लिए रेगेक्स का उपयोग करने के लिए कई सुविधाएँ प्रदान करता है (यादृच्छिक पीढ़ी, यह सूचकांक के आधार पर स्ट्रिंग उत्पन्न करता है, सभी स्ट्रिंग उत्पन्न करता है ..) इसे यहाँ देखें
Mifmif

एक अन्य विकल्प हो सकता है इस
व्लादिस्लाव Varslavans

जवाबों:


40

संपादित करें: जैसा कि टिप्पणियों में उल्लेख किया गया है, इसे प्राप्त करने के लिए Google कोड पर एक पुस्तकालय उपलब्ध है: https://code.google.com/archive/p/e/ee/

Mifmif द्वारा सुझाए गए https://github.com/mifmif/Generex को भी देखें

वास्तविक सन्देश:

सबसे पहले, एक जटिल पर्याप्त regexp के साथ, मेरा मानना ​​है कि यह असंभव हो सकता है। लेकिन आपको सरल रीजैक्स के लिए कुछ एक साथ रखने में सक्षम होना चाहिए।

यदि आप java.util.regex.Pattern के स्रोत कोड पर एक नज़र डालें, तो आप देखेंगे कि यह नोड उदाहरणों के आंतरिक प्रतिनिधित्व का उपयोग करता है। प्रत्येक अलग-अलग पैटर्न घटकों में एक नोड उपवर्ग का अपना कार्यान्वयन है। इन नोड्स को एक पेड़ में व्यवस्थित किया जाता है।

एक आगंतुक का निर्माण करके जो इस पेड़ का पता लगाता है, आपको एक अतिभारित जनरेटर विधि या किसी प्रकार के बिल्डर को कॉल करने में सक्षम होना चाहिए जो किसी चीज़ को एक साथ मिलाता है।


2
मुझे यकीन नहीं है कि Xeger वह अच्छा है। यह चरित्र वर्गों को संभाल नहीं सकता है। यह एक साधारण को पहचानने में विफल रहता है [\w]उनकी विकि की अंतिम पंक्ति पर एक नज़र हमें बताती है।
जॉन रेड

2
ध्यान दें कि ये निर्भर करते हैं dk.brics.automatonइसलिए तृतीय पक्ष पोम निर्भरता जोड़ने के लिए तैयार रहें। अधिकांश लोगों को यह बुरा नहीं लगता है, लेकिन मैं चाहता हूं कि कुछ अधिक कॉम्पैक्ट था।
श्रीधर सरनोबत

Xeger और generex के लिए विकल्प है। इसमें इन सभी कमियों का अभाव है और यह अप्रचलित नहीं है। कृपया मेरे उत्तर के लिए नीचे स्क्रॉल करें।
व्लादिस्लाव वर्स्लावन्स

"सबसे पहले, एक जटिल पर्याप्त regexp के साथ, मेरा मानना ​​है कि यह असंभव हो सकता है।" - यह कड़ाई से सच नहीं है : किसी भी चीज के खिलाफ गुजरने वाला कोई भी रेगेक्स भी एक वैध इनपुट उत्पन्न कर सकता है। स्पष्टीकरण: रेग्जेस चॉम्स्की पदानुक्रम पर टाइप -3 हैं, जिसका अर्थ है कि उन्हें एफएसएम के रूप में व्यक्त किया जा सकता है। एफएसएम के माध्यम से कदम रखते समय, प्रत्येक किनारे को अगले चरित्र के लिए एक नियम के रूप में व्याख्या की जाती है, इस प्रकार एक एफएसएम का उपयोग अनुक्रमों को पार्स या उत्पन्न करने के लिए किया जा सकता है । यदि एफएसएम में टर्मिनल के लिए एक रास्ता है, तो एक वैध अनुक्रम निर्धारित किया जा सकता है। इसलिए, यह केवल "असंभव" है अगर टर्मिनल के लिए कोई रास्ता नहीं है (जो एक बेकार रेगेक्स होगा)।
लॉरेंस Wagerfield

22

मूल पोस्टर की मदद करने के लिए बहुत देर हो चुकी है, लेकिन यह एक नवागंतुक की मदद कर सकता है। जेनरेक्स एक उपयोगी जावा लाइब्रेरी है जो स्ट्रिंग उत्पन्न करने के लिए रीगेक्स का उपयोग करने के लिए कई सुविधाएँ प्रदान करता है (यादृच्छिक पीढ़ी, इसके सूचकांक के आधार पर एक स्ट्रिंग पैदा करना, सभी तार उत्पन्न करना ...)।

उदाहरण :

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) से संबंधित है। के अनुसार नियम , इस जरूरत को लाया जा सकता है।


11
ऐसा लगता है कि Generex आपका अपना प्रोजेक्ट है। क्या आप अपनी पोस्ट में इस बात का उल्लेख करेंगे कि यह आपकी अपनी परियोजना है, यहाँ के नियमों के अनुसार ?
ब्रायन मैककिनटन

20

Xeger (Java) इसे करने में सक्षम है:

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

1
Xeger अच्छी तरह से काम करता है। लेकिन यकीन है कि आप है कि बनाने के automaton जार वर्ग पथ पर या अपने पोम / Gradle में
Delicia Brummitt

5

मैं अपनी खुद की लाइब्रेरी को रोल करने की जड़ में चला गया हूं (सी # में लेकिन एक जावा डेवलपर के लिए समझना आसान होना चाहिए)।

Rxrdg ने वास्तविक जीवन परियोजना के लिए परीक्षण डेटा बनाने की समस्या के समाधान के रूप में शुरू किया। मूल विचार यादृच्छिक डेटा बनाने के लिए मौजूदा (नियमित अभिव्यक्ति) सत्यापन पैटर्न का लाभ उठाना है जो इस तरह के पैटर्न के अनुरूप है। इस तरह वैध यादृच्छिक डेटा बनाया जाता है।

सरल रेगेक्स पैटर्न के लिए एक पार्सर लिखना उतना मुश्किल नहीं है। तार उत्पन्न करने के लिए अमूर्त सिंटैक्स ट्री का उपयोग करना और भी आसान होना चाहिए।


लिंक अब रिपॉजिटरी की ओर इशारा नहीं करता है। मैं openhub.net/p/rxrdg के साथ जाऊंगा । हालांकि, समाधान का निर्माण नहीं होता है?
विवेके जुले

4

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) भी होगा जो आपको दो मानों के बीच एक यादृच्छिक पत्र देता है।


4

यह प्रश्न वास्तव में पुराना है, हालांकि समस्या मेरे लिए वास्तविक थी। मैंने xeger और Generex की कोशिश की है और वे मेरे प्रतिगमन को पूरा नहीं करते हैं। वे वास्तव में कुछ रेगेक्स पैटर्न (जैसे a{60000}) या दूसरों के लिए (जैसे (A|B|C|D|E|F)) संसाधित करने में विफल रहते हैं, वे केवल सभी संभावित मूल्यों का उत्पादन नहीं करते हैं। चूँकि मुझे कोई अन्य उपयुक्त समाधान नहीं मिला - मैंने अपनी लाइब्रेरी बनाई है।

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

मावेन सेंट्रल पर भी कलाकृतियाँ उपलब्ध हैं।

उपयोग उदाहरण:

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

3

मुझे पता है कि पहले से ही एक स्वीकृत उत्तर है, लेकिन मैं रेडगेट के डेटा जेनरेटर (क्रेग के उत्तर में उल्लिखित) का उपयोग कर रहा हूं और यह मेरे द्वारा फेंके गए हर चीज के लिए बहुत अच्छी तरह से काम करता है। यह त्वरित है और जो मुझे पंजीकरण कोड जैसी चीजों के लिए वास्तविक डेटा उत्पन्न करने के लिए एक ही regex का उपयोग करने के लिए इच्छुक छोड़ देता है।

यह एक रेगीक्स लेता है जैसे:

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

और यह अद्वितीय कोड के टन उत्पन्न करता है जैसे:

LLK-32U

क्या यह कोई बड़ा गुप्त एल्गोरिथ्म है जिसे RedGate ने खोजा है और हम सब भाग्य से बाहर हैं या यह कुछ ऐसा है जिसे हम केवल वास्तव में कर सकते हैं?


3

मैं उड़ान पर हूं और बस सवाल देखा है: मैंने सबसे आसान लेकिन अक्षम और अधूरा समाधान लिखा है। मुझे आशा है कि यह आपको अपना स्वयं का पार्सर लिखना शुरू करने में मदद कर सकता है:

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);
}

आप संकेत करना चाह सकते हैं कि पैटर्न इनपुट के रूप में किस प्रकार के तार का उपयोग किया जाता है। सबसे पहले, स्रोत कोड से ऐसी चीजों को निर्धारित करना आसान नहीं है। दूसरा, यदि स्रोत कोड में कोई गलती या अशुद्धता है, तो यह देखने का कोई तरीका नहीं है कि वे जानबूझकर हैं या नहीं।
मार्टन बोडेवेस

StringTokenizer एक विरासत वर्ग है जिसे संगतता कारणों से बरकरार रखा जाता है, हालांकि इसका उपयोग नए कोड में हतोत्साहित किया जाता है। यह अनुशंसा की जाती है कि इस कार्यक्षमता को प्राप्त करने वाला कोई भी स्ट्रिंग या java.util.regex पैकेज के विभाजन विधि का उपयोग करे।
रोहित

2

आपको अपना स्वयं का पार्सर लिखना होगा, जैसे स्ट्रिंग के लेखक :: रैंडम (पर्ल) ने किया था। वास्तव में, वह उस मॉड्यूल में कहीं भी रेगेक्स का उपयोग नहीं करता है, यह सिर्फ वही है जो पर्ल-कोडर्स के लिए उपयोग किया जाता है।

दूसरी ओर, हो सकता है कि आप कुछ संकेत प्राप्त करने के लिए स्रोत पर एक नज़र डाल सकते हैं ।


संपादित करें: लानत है, ब्लेयर ने मुझे 15 सेकंड से पंच तक हराया।


1

यह एक पूर्ण PCRE regexp का समर्थन करने से दूर है, लेकिन मैंने regexp जैसी स्ट्रिंग लेने और उस पर एक भिन्नता उत्पन्न करने के लिए निम्नलिखित रूबी विधि लिखी। (भाषा-आधारित कैप्चा के लिए।)

# 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

1

यह प्रश्न बहुत पुराना है, लेकिन मैंने अपनी खोज पर इसे पार कर लिया है, इसलिए मैं उन अन्य लोगों के लिए एक युगल लिंक शामिल करूंगा जो अन्य भाषाओं में समान कार्यक्षमता की खोज कर रहे होंगे।


0

यदि आप "क्रिटिकल" स्ट्रिंग्स जेनरेट करना चाहते हैं, तो आप विचार कर सकते हैं:

EGRET http://elarson.pythonanywhere.com/ जो आपके नियमित भावों को कवर करते हुए "दुष्ट" तार उत्पन्न करता है

MUTREX http://cs.unibg.it/mutrex/ जो regex उत्परिवर्तन द्वारा दोष का पता लगाने के तार उत्पन्न करता है

दोनों शैक्षणिक उपकरण हैं (मैं बाद के लेखकों में से एक हूं) और यथोचित काम करते हैं।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.