संस्करण संख्या पार्सिंग के लिए एक regex


84

मेरे पास निम्नलिखित फ़ॉर्म का एक संस्करण संख्या है:

version.release.modification

जहाँ संस्करण, रिलीज़ और संशोधन या तो अंकों का एक सेट है या '*' वाइल्डकार्ड वर्ण। इसके अतिरिक्त, इनमें से कोई भी संख्या (और किसी भी पूर्ववर्ती) गायब हो सकती है।

तो निम्नलिखित मान्य और पार्स हैं:

1.23.456 = version 1, release 23, modification 456
1.23     = version 1, release 23, any modification
1.23.*   = version 1, release 23, any modification
1.*      = version 1, any release, any modification
1        = version 1, any release, any modification
*        = any version, any release, any modification

लेकिन ये मान्य नहीं हैं:

*.12
*123.1
12*
12.*.34

क्या कोई मुझे रिलीज़, संस्करण और संशोधन संख्याओं को मान्य और पुनः प्राप्त करने के लिए एक बहुत-जटिल रीजेक्स प्रदान नहीं कर सकता है?


मुझे यकीन नहीं है कि एक "सरल" संभव है।
सविस्तार

जवाबों:


96

मैं इस प्रारूप को व्यक्त करूंगा:

"1-3 डॉट-अलग किए गए घटक, प्रत्येक संख्यात्मक को छोड़कर जो पिछले एक हो सकता है *"

Regexp के रूप में, यह है:

^(\d+\.)?(\d+\.)?(\*|\d+)$

[जोड़ने के लिए संपादित करें: यह समाधान मान्य करने का एक संक्षिप्त तरीका है, लेकिन यह बताया गया है कि मूल्यों को निकालने के लिए अतिरिक्त काम की आवश्यकता होती है। यह स्वाद की बात है कि क्या इससे निपटने के लिए regexp को उलझाकर, या मिलान किए गए समूहों को संसाधित करके।

मेरे समाधान में, समूह "."पात्रों को पकड़ते हैं । इसे गैर-कैप्चरिंग समूहों के उपयोग से निपटा जा सकता है जैसा कि अज़बोरली के उत्तर में है।

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

Regexp के बाद दोनों मुद्दों से निपटने के लिए पर्ल कोड कुछ इस तरह हो सकता है:

@version = ();
@groups = ($1, $2, $3);
foreach (@groups) {
    next if !defined;
    s/\.//;
    push @version, $_;
}
($major, $minor, $mod) = (@version, "*", "*");

जो वास्तव में बंटवारे से कम नहीं है "." ]


1
कुछ गैर-कैप्चरिंग ग्रुप्स (नीचे मेरा उत्तर देखें) जोड़ने का मतलब है कि कैप्चरिंग ग्रुप्स 'अनुगामी को कैप्चर नहीं करते हैं।' ^ ^?: (\ _ डी +)।)? (?: (\ _ डी +) \।)? (* = \ _ d +) $ धन्यवाद!
एंड्रयू बोरले

उस एक के साथ एकमात्र समस्या - एक बहुत अच्छा और साफ प्रस्ताव होना - यह है कि समूह सही नहीं हैं क्योंकि 1.2 लालच के कारण पहले और 2 तीसरे समूह में 1 पर कब्जा कर लेंगे।
जर्दोलफ

39

रेगेक्स का उपयोग करें और अब आपको दो समस्याएं हैं। मैं बात को डॉट्स ("") पर विभाजित करता हूं, फिर सुनिश्चित करें कि प्रत्येक भाग या तो वाइल्डकार्ड है या अंकों का सेट (regex अभी एकदम सही है)। यदि बात वैध है, तो आप विभाजन का सही हिस्सा वापस कर सकते हैं।


11

यह काम कर सकता है:

^(\*|\d+(\.\d+){0,2}(\.\*)?)$

शीर्ष स्तर पर, "*" एक मान्य संस्करण संख्या का एक विशेष मामला है। अन्यथा, यह एक संख्या से शुरू होता है। फिर शून्य, एक, या दो ".nn" क्रम होते हैं, इसके बाद एक वैकल्पिक "। *" होता है। यह regex 1.2.3 को स्वीकार करेगा। * जो आपके आवेदन में अनुमति दे भी सकता है और नहीं भी।

मिलान किए गए अनुक्रमों को प्राप्त करने के लिए कोड, विशेष रूप से (\.\d+){0,2}भाग, आपके विशेष रेगेक्स लाइब्रेरी पर निर्भर करेगा।


बहुत बढ़िया जवाब! मुझे लगता है कि आपको 1.2.3.4 मिलान को रोकने के लिए {0,2} के लिए अनसैप्ड * स्वैप करना चाहिए। अपने regexp लाइब्रेरी के आधार पर आप पैटर्न को ^ (<पैटर्न>) $ में संलग्न करना चाह सकते हैं यदि आप केवल एक मैच के बजाय एक खोज कर सकते हैं।
डेव वेब

^ (* | \ D + (\। \ D +) {0,1} (?: (\ _। *।)? - (\ _। D +)?)) में थोड़ा सा परिवर्तन 1.2.3 को अमान्य कर देगा। *
Piet

2
पीटर: मुझे लगता है कि मैं अब जहां हूं, वहां रुकने जा रहा हूं। यह जल्दी से "अब आपको दो समस्याएं हैं" क्षेत्र में मिल रहा है। :)
ग्रेग हेवगिल सेप

11

प्रतिसाद के लिए धन्यवाद! यह इक्का है :)

OneByOne के उत्तर (जो मुझे सबसे सरल लगता था) के आधार पर, मैंने कुछ गैर-कैप्चरिंग समूहों ('?:' 'पुर्जों -' 'को गैर-कैप्चरिंग ग्रुप्स' 'से परिचित कराने के लिए VonC को धन्यवाद दिया), इसलिए वे समूह जो केवल कैप्चर करते हैं! अंक या * वर्ण होते हैं।

^(?:(\d+)\.)?(?:(\d+)\.)?(\*|\d+)$

सभी को बहुत बहुत धन्यवाद!


1
क्या आप इसे अपने प्रश्न के बदले संपादित के रूप में जोड़ सकते हैं? इस तरह से सही उत्तर शीर्ष के करीब है
svrist

1
समूह के नाम के साथ: ^ (?:? (? <प्रमुख> \ d +)।)? (?:? (? <? <मामूली> \ d +) \।)? (? <निर्माण> * *। \ D +) $
javacavaj

1
समर्थन तोड़फोड़ (थोड़ा और अधिक)। - "1.2.3-अल्फा + abcdedf.lalal" -match "^? (?: (\ D + \ _)।?: ?: ((d d +) \?)? (* * \ _ D +)? (?: ?: ([A-Za-z0-9 \।] +)?)? (?: \ + ([A-Za-z0-9 \9]] +))? $ "
Sam

खबरदार है कि किसी एक नंबर से बने संस्करण के मामले में यह तीसरे से मेल खाएगा (\*|\d+), पहले ^(?:(\d+)\.)?समूह से नहीं।
पियोट्र डोब्रोगोस्ट

8

मेरे 2 सेंट: मेरे पास यह परिदृश्य था: मुझे एक स्ट्रिंग शाब्दिक से संस्करण संख्याओं को पार्स करना था। (मुझे पता है कि यह मूल प्रश्न से बहुत अलग है, लेकिन संस्करण संख्या को पार्स करने के लिए regex खोजने के लिए googling ने इस धागे को शीर्ष पर दिखाया, इसलिए इस उत्तर को यहां जोड़ दें)

तो स्ट्रिंग शाब्दिक कुछ इस तरह होगा: "सेवा संस्करण 1.2.35.564 चल रहा है!"

मुझे इस शाब्दिक में से 1.2.35.564 को पार्स करना था। @ जाबोरले से एक क्यू लेना, मेरा रेगेक्स इस प्रकार है:

(?:(\d+)\.)?(?:(\d+)\.)?(?:(\d+)\.\d+)

यह परीक्षण करने के लिए एक छोटा C # स्निपेट नीचे जैसा दिखता है:

void Main()
{
    Regex regEx = new Regex(@"(?:(\d+)\.)?(?:(\d+)\.)?(?:(\d+)\.\d+)", RegexOptions.Compiled);

    Match version = regEx.Match("The Service SuperService 2.1.309.0) is Running!");
    version.Value.Dump("Version using RegEx");   // Prints 2.1.309.0        
}

मुझे पता है कि आप एक वैकल्पिक स्थिति और मामले का वर्णन कर रहे हैं, लेकिन बस पूरा होने के लिए: सेमी वीर को 'स्ट्रिंग' प्रारूप की आवश्यकता होती है X.Y.Z(इसलिए, ठीक तीन भाग), जहां एक्स और वाई गैर-नकारात्मक पूर्णांक होना चाहिए और नहीं अतिरिक्त अग्रणी शून्य। देखें semver.org
जोकेम शुल्नेक्लोपर

1
@JochemSchulenklopper धन्यवाद, मैं SemVer के बारे में जानता हूं, हालांकि इस सवाल में SemVer के बारे में कुछ भी उल्लेख नहीं है।
सुधांशु मिश्रा

1
सच। मुझे इस प्रश्न का उल्लेख एक सहयोगी द्वारा सेमी वीरिंग स्ट्रिंग को पार्स करने के बारे में किया गया था, ताकि मेरे उत्तरों को पढ़ने में कठिनाई हुई।
जोकेम शुल्नेक्लोपर

7

पता नहीं कि आप किस प्लेटफ़ॉर्म पर हैं, लेकिन .NET में सिस्टम है। वर्जन क्लास जो आपके लिए "nnnn" वर्जन नंबर को पार्स करेगी।


नहीं, यह संस्करण 1.0 के बाद से वहाँ है
डंकन स्मार्ट

5

मैं विभाजित सुझाव से सहमत हूं।

Ive ने पर्ल में आपकी समस्या के लिए एक "परीक्षक" बनाया

#!/usr/bin/perl -w


@strings = ( "1.2.3", "1.2.*", "1.*","*" );

%regexp = ( svrist => qr/(?:(\d+)\.(\d+)\.(\d+)|(\d+)\.(\d+)|(\d+))?(?:\.\*)?/,
            onebyone => qr/^(\d+\.)?(\d+\.)?(\*|\d+)$/,
            greg => qr/^(\*|\d+(\.\d+){0,2}(\.\*)?)$/,
            vonc => qr/^((?:\d+(?!\.\*)\.)+)(\d+)?(\.\*)?$|^(\d+)\.\*$|^(\*|\d+)$/,
            ajb => qr/^(?:(\d+)\.)?(?:(\d+)\.)?(\*|\d+)$/,
            jrudolph => qr/^(((\d+)\.)?(\d+)\.)?(\d+|\*)$/
          );

  foreach my $r (keys %regexp){
    my $reg = $regexp{$r};
    print "Using $r regexp\n";
foreach my $s (@strings){
  print "$s : ";

    if ($s =~m/$reg/){
    my ($main, $maj, $min,$rev,$ex1,$ex2,$ex3) = ("any","any","any","any","any","any","any");
    $main = $1 if ($1 && $1 ne "*") ;
    $maj = $2 if ($2 && $2 ne "*") ;
    $min = $3 if ($3 && $3 ne "*") ;
    $rev = $4 if ($4 && $4 ne "*") ;
    $ex1 = $5 if ($5 && $5 ne "*") ;
    $ex2 = $6 if ($6 && $6 ne "*") ;
    $ex3 = $7 if ($7 && $7 ne "*") ;
    print "$main $maj $min $rev $ex1 $ex2 $ex3\n";

  }else{
  print " nomatch\n";
  }
  }
print "------------------------\n";
}

मौजूदा उत्पादन:

> perl regex.pl
Using onebyone regexp
1.2.3 : 1. 2. 3 any any any any
1.2.* : 1. 2. any any any any any
1.* : 1. any any any any any any
* : any any any any any any any
------------------------
Using svrist regexp
1.2.3 : 1 2 3 any any any any
1.2.* : any any any 1 2 any any
1.* : any any any any any 1 any
* : any any any any any any any
------------------------
Using vonc regexp
1.2.3 : 1.2. 3 any any any any any
1.2.* : 1. 2 .* any any any any
1.* : any any any 1 any any any
* : any any any any any any any
------------------------
Using ajb regexp
1.2.3 : 1 2 3 any any any any
1.2.* : 1 2 any any any any any
1.* : 1 any any any any any any
* : any any any any any any any
------------------------
Using jrudolph regexp
1.2.3 : 1.2. 1. 1 2 3 any any
1.2.* : 1.2. 1. 1 2 any any any
1.* : 1. any any 1 any any any
* : any any any any any any any
------------------------
Using greg regexp
1.2.3 : 1.2.3 .3 any any any any any
1.2.* : 1.2.* .2 .* any any any any
1.* : 1.* any .* any any any any
* : any any any any any any any
------------------------

यह अच्छा होगा, क्योंकि OneByOne सबसे सीधा-सादा दिखता है।
१२:

आपको गलत लोगों का भी परीक्षण करना चाहिए। आप OneByOne के डॉट्स को उद्धृत करने से चूक गए।
jrudolph

डॉट्स, और अधिक regexps
svrist

4

यह आपके द्वारा निर्धारित किए गए कार्यों के लिए होना चाहिए। यह वाइल्ड कार्ड पोजीशन पर टिका है और नेस्टेड रेगेक्स है:

^((\*)|([0-9]+(\.((\*)|([0-9]+(\.((\*)|([0-9]+)))?)))?))$

http://imgur.com/3E492.png


4

मैंने बहुत सारे उत्तर देखे हैं, लेकिन ... मेरे पास एक नया है। यह मेरे लिए कम से कम काम करता है। मैंने एक नया प्रतिबंध जोड़ा है। संस्करण संख्याएं किसी भी शून्य के बाद (प्रमुख, मामूली या पैच) शुरू नहीं हो सकती हैं।

01.0.0 वैध नहीं है। 1.0.0 वैध है। 10.0.10 वैध है, 1.0.0000 वैध नहीं है

^(?:(0\\.|([1-9]+\\d*)\\.))+(?:(0\\.|([1-9]+\\d*)\\.))+((0|([1-9]+\\d*)))$

यह पिछले एक पर आधारित है। लेकिन मुझे यह समाधान बेहतर लगता है ... मेरे लिए;)

का आनंद लें!!!


3

एक और प्रयास:

^(((\d+)\.)?(\d+)\.)?(\d+|\*)$

यह समूह 4,5,6 BUT में तीन भाग देता है: वे दाईं ओर संरेखित होते हैं। तो 4,5 या 6 में से पहला गैर-शून्य संस्करण क्षेत्र देता है।

  • 1.2.3 1,2,3 देता है
  • १.२। * १,२ देता है, *
  • 1.2 शून्य देता है, 1,2
  • *** अशक्त, अशक्त देता है, *
  • 1. "मैं अशक्त, 1, *

3
^(?:(\d+)\.)?(?:(\d+)\.)?(\*|\d+)$

शायद एक और अधिक संक्षिप्त एक हो सकता है:

^(?:(\d+)\.){0,2}(\*|\d+)$

इसके बाद इसे 1.2.3.4.5 तक बढ़ाया जा सकता है। या {0,2} के बजाय * या {2} का उपयोग करके XYZ के लिए बिल्कुल प्रतिबंधित है


3

मुझे संस्करण संख्याओं के लिए खोज / मिलान की आवश्यकता थी, जो मावन सम्मेलन या यहां तक ​​कि सिर्फ एक अंक का अनुसरण करता है। लेकिन किसी भी मामले में कोई क्वालिफायर नहीं। यह अजीबोगरीब था, इसमें मुझे समय लगा तब मैं इसके साथ आया:

'^[0-9][0-9.]*$'

यह सुनिश्चित करता है कि संस्करण,

  1. एक अंक से शुरू होता है
  2. अंकों की कोई भी संख्या हो सकती है
  3. केवल अंक और '।' अनुमति हैं

एक कमी यह है कि संस्करण 'के साथ भी समाप्त हो सकता है।' लेकिन यह संस्करण की अनिश्चित लंबाई को संभाल सकता है (यदि आप इसे कॉल करना चाहते हैं तो पागल संस्करण)

मेल खाता है:

  • 1.2.3
  • 1.09.5
  • 3.4.4.5.7.8.8।
  • 23.6.209.234.3

अगर आप इससे नाखुश नहीं हैं '।' समाप्त, हो सकता है कि आप एंडविथ तर्क के साथ संयोजन कर सकते हैं


अंतिम अंक से छुटकारा पाने के लिए, शायद आप यह कोशिश करना चाहेंगे:(\d+)(.\d+)*
cassioso

2
(?ms)^((?:\d+(?!\.\*)\.)+)(\d+)?(\.\*)?$|^(\d+)\.\*$|^(\*|\d+)$

क्या आपके 6 पहले उदाहरणों से मेल खाता है, और 4 अन्य को अस्वीकार करता है

  • समूह 1: प्रमुख या प्रमुख। मामूली या '*'
  • समूह 2 यदि मौजूद है: नाबालिग या *
  • समूह 3 यदि मौजूद है: *

आप निकाल सकते हैं '(ms)'
मैंने इसका इस्तेमाल इस regexp को इंगित करने के लिए क्विकरेक्स के माध्यम से मल्टी-लाइन्स पर लागू करने के लिए किया है


2

यह 1.2.3 से मेल खाता है। * भी

^ (* |। \ D + (\ d +) {0,2} (*)।?) $

मैं कम सुरुचिपूर्ण प्रस्ताव देगा:

(* | \ D + (\ d +) (*)।?।?) | \ D + \ d + \ d +)।।


2

ध्यान रखें कि regexp लालची होते हैं, इसलिए यदि आप संस्करण संख्या स्ट्रिंग के भीतर खोज रहे हैं न कि किसी बड़े पाठ के भीतर, अपने स्ट्रिंग के प्रारंभ और अंत को चिह्नित करने के लिए ^ और $ का उपयोग करें। ग्रेग से regexp ठीक काम करने लगता है (बस यह मेरे संपादक में एक त्वरित प्रयास दिया), लेकिन आपके पुस्तकालय / भाषा पर निर्भर करता है कि पहला भाग अभी भी गलत संस्करण संख्याओं के भीतर "*" से मेल खा सकता है। शायद मुझे कुछ याद आ रहा है, क्योंकि मैंने एक-एक साल से Regexp का इस्तेमाल नहीं किया है।

यह सुनिश्चित करना चाहिए कि आप केवल सही संस्करण संख्या पा सकते हैं:

^ (\ * |।।? \ D + (\ \ d +) * (\ \ *)) $

संपादित करें: वास्तव में greg ने उन्हें पहले से ही जोड़ा है और यहां तक ​​कि उनके समाधान में सुधार किया है, मैं बहुत धीमा हूं :)


2

ऐसा लगता है कि आप चाहते हैं कि वास्तव में क्या करता है एक regex है (यानी केवल उन मामलों को स्वीकार करें जो आपको चाहिए और अन्य सभी को अस्वीकार कर दें और तीन घटकों के लिए कुछ समूह लौटाएं)। मैंने इसे आजमाया है और इसके साथ आता हूं:

^(\*|(\d+(\.(\d+(\.(\d+|\*))?|\*))?))$

IMO (मैंने बड़े पैमाने पर परीक्षण नहीं किया है) यह इनपुट के लिए एक सत्यापनकर्ता के रूप में ठीक काम करना चाहिए, लेकिन समस्या यह है कि यह regex घटकों को पुनर्प्राप्त करने का एक तरीका प्रदान नहीं करता है। उसके लिए आपको अभी भी एक अवधि में विभाजन करना होगा।

यह समाधान ऑल-इन-वन नहीं है, लेकिन प्रोग्रामिंग में अधिकांश समय इसकी आवश्यकता नहीं है। बेशक यह अन्य प्रतिबंधों पर निर्भर करता है जो आपके कोड में हो सकते हैं।


2

XSD तत्व निर्दिष्ट करना:

<xs:simpleType>
    <xs:restriction base="xs:string">
        <xs:pattern value="[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}(\..*)?"/>
    </xs:restriction>
</xs:simpleType>

2

एक अच्छी कसरत के रूप में मेरा इस पर ध्यान दिया जाता है - vparse , जिसका एक छोटा सा स्रोत है , एक साधारण कार्य के साथ:

function parseVersion(v) {
    var m = v.match(/\d*\.|\d+/g) || [];
    v = {
        major: +m[0] || 0,
        minor: +m[1] || 0,
        patch: +m[2] || 0,
        build: +m[3] || 0
    };
    v.isEmpty = !v.major && !v.minor && !v.patch && !v.build;
    v.parsed = [v.major, v.minor, v.patch, v.build];
    v.text = v.parsed.join('.');
    return v;
}

2

इन नियमों का पालन करने वाले संस्करण संख्याओं के लिए: - क्या केवल अंक और बिंदु हैं - एक डॉट के साथ शुरू या समाप्त नहीं हो सकते - एक साथ दो बिंदु नहीं हो सकते

इसने मेरे साथ छल किया।

^(\d+)((\.{1}\d+)*)(\.{0})$

मान्य मामले हैं:

1, 0.1, 1.2.1



1

कभी-कभी संस्करण संख्याओं में अल्फ़ान्यूमेरिक माइनर जानकारी (जैसे 1.2.0b या 1.2.0-बीटा ) हो सकती है। इस मामले में मैं इस regex का उपयोग कर रहा हूं:

([0-9]{1,4}(\.[0-9a-z]{1,6}){1,5})

0

मुझे यह मिला, और यह मेरे लिए काम करता है:

/(\^|\~?)(\d|x|\*)+\.(\d|x|\*)+\.(\d|x|\*)+
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.