it-swarm-ko.tech

버전 번호 구문 분석을위한 정규식

다음 형식의 버전 번호가 있습니다.

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

누구든지 릴리스, 버전 및 수정 번호를 확인하고 검색하기 위해 너무 복잡하지 않은 정규식을 제공 할 수 있습니까?

73
Andrew Borley

형식을 다음과 같이 표현합니다.

"1-3 개의 점으로 분리 된 구성 요소 (마지막 구성 요소를 제외한 각 숫자는 * 일 수 있음)

정규 표현식으로 다음과 같습니다.

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

[추가 편집 :이 솔루션은 간결한 검증 방법이지만 값을 추출하려면 추가 작업이 필요하다는 것이 지적되었습니다. 정규 표현식을 복잡하게하거나 일치하는 그룹을 처리하여이 문제를 처리할지 여부는 맛의 문제입니다.

내 솔루션에서 그룹은 "." 문자를 캡처합니다. 이것은 ajborley의 답변에서와 같이 캡처하지 않은 그룹을 사용하여 처리 할 수 ​​있습니다.

또한 가장 오른쪽에있는 그룹은 구성 요소가 3 개 미만인 경우에도 마지막 구성 요소를 캡처하므로, 예를 들어 두 구성 요소 입력은 첫 번째 및 마지막 그룹을 캡처하고 가운데 구성 요소는 정의되지 않습니다. 나는 이것이 지원되는 욕심없는 그룹에 의해 처리 될 수 있다고 생각합니다.

정규 표현식 후 두 가지 문제를 모두 처리하는 Perl 코드는 다음과 같습니다.

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

"."에서 나누는 것보다 짧지 않습니다.

76
Steve Jessop

정규식을 사용하면 이제 두 가지 문제가 있습니다. 물건을 점 ( ".")으로 분할 한 다음 각 부분이 와일드 카드 또는 숫자 세트인지 확인하십시오 (정규식은 이제 완벽합니다). 일이 유효하면 올바른 분할 청크를 반환합니다.

38
Paweł Hajdan

이것은 작동 할 수 있습니다 :

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

최상위 레벨에서 "*"는 유효한 버전 번호의 특수한 경우입니다. 그렇지 않으면 숫자로 시작합니다. 그런 다음 0 개, 1 개 또는 2 개의 ".nn"시퀀스와 선택적인 ". *"가 있습니다. 이 정규식은 귀하의 신청서에 허용되거나 허용되지 않는 1.2.3. *를 허용합니다.

일치하는 시퀀스, 특히 (\.\d+){0,2} 부분은 특정 정규식 라이브러리에 따라 다릅니다.

11
Greg Hewgill

모든 답변에 감사드립니다! 이것은 에이스입니다 :)

OneByOne의 답변 (가장 단순 해 보임)을 기반으로 캡처하지 않은 그룹 ( '(? :'부분-캡처하지 않은 그룹을 소개 해준 VonC 덕분에) 덕분에 캡처 한 그룹 만 추가했습니다. 숫자 또는 * 문자를 포함합니다.

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

많은 분들께 감사드립니다!

11
Andrew Borley

내 2 센트 :이 시나리오가 있습니다 : 문자열 리터럴에서 버전 번호를 구문 분석해야했습니다. (이것은 원래 질문과는 매우 다르다는 것을 알고 있지만 버전 번호를 구문 분석하기위한 정규식을 찾으려면 인터넷 이이 스레드를 맨 위에 표시 했으므로 여기 에이 답변을 추가하십시오)

따라서 문자열 리터럴은 "서비스 버전 1.2.35.564가 실행 중입니다!"와 같습니다.

이 리터럴에서 1.2.35.564를 구문 분석해야했습니다. @ajborley에서 힌트를 얻은 내 정규식은 다음과 같습니다.

(?:(\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        
}
7
Sudhanshu Mishra

현재 사용중인 플랫폼을 모르지만 .NET에는 "n.n.n.n"버전 번호를 구문 분석하는 System.Version 클래스가 있습니다.

7
Duncan Smart

나는 분할 제안에 동의하는 경향이 있습니다.

펄에서 문제에 대한 "테스터"를 만들었습니다

#!/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
------------------------
5
svrist

이것은 당신이 규정 한 것에 효과가 있습니다. 와일드 카드 위치에 달려 있으며 중첩 된 정규식입니다.

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

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

4
nomuus

많은 답변을 보았지만 ... 새로운 답변이 있습니다. 그것은 적어도 나를 위해 작동합니다. 새로운 제한을 추가했습니다. 버전 번호는 0 다음에 다른 숫자로 시작될 수 없습니다 (주, 부 또는 패치).

01.0.0이 유효하지 않음 1.0.0이 유효합니다 10.0.10이 유효합니다 1.0.0000이 유효하지 않습니다

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

이전 버전을 기반으로합니다. 그러나 나는이 솔루션을 더 잘 본다.

즐겨!!!

4
Israel Romero

다른 시도 :

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

이것은 그룹 4,5,6에서 세 부분을 제공하지만 오른쪽에 정렬됩니다. 따라서 4, 5 또는 6 중 null이 아닌 첫 번째 버전은 버전 필드를 제공합니다.

  • 1.2.3은 1,2,3을 준다
  • 1.2. *는 1,2, *를줍니다.
  • 1.2는 null, 1,2를 제공합니다
  • *** null, null을 제공합니다. *
  • 1. *는 null, 1, *를 제공합니다.
3
jrudolph
^(?:(\d+)\.)?(?:(\d+)\.)?(\*|\d+)$

아마도 더 간결한 것은 다음과 같습니다.

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

그런 다음이를 1.2.3.4.5. *로 향상 시키거나 {0,2} 대신 * 또는 {2}를 사용하여 X.Y.Z로 정확하게 제한 할 수 있습니다.

3
ofaurax

버전 번호를 검색/일치해야한다는 요구 사항이 있었으며 메이븐 규칙 또는 심지어 한 자리 수를 따릅니다. 그러나 어떤 경우에도 한정자가 없습니다. 그것은 독특했습니다. 시간이 걸렸고 나는 이것을 생각해 냈습니다.

'^[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

'.'에 만족하지 않으면 끝, 논리와 끝을 결합 할 수 있습니다

3
Shiva

정확히 원하는 것을 수행하는 정규 표현식을 사용하는 것은 매우 어렵습니다 (즉, 필요한 경우 만 수락하고 all other and 세 구성 요소에 대한 일부 그룹을 반환합니다). 나는 그것을 시도하고 이것을 생각해 냈다.

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

IMO (내가 광범위하게 테스트하지는 않았 음)는 입력의 유효성 검사기로 잘 작동하지만 문제는이 정규식이 구성 요소를 검색하는 방법을 제공하지 않는다는 것입니다. 이를 위해서는 여전히 기간 분할을해야합니다.

이 솔루션은 올인원은 아니지만 대부분의 경우 프로그래밍 할 필요가 없습니다. 물론 이것은 코드에서 가질 수있는 다른 제한 사항에 따라 다릅니다.

2
rslite

Regexp는 탐욕 스러우므로 더 큰 텍스트가 아닌 버전 번호 문자열 내에서만 검색하는 경우 ^ 및 $를 사용하여 문자열의 시작과 끝을 표시하십시오. Greg의 정규 표현식은 잘 작동하는 것 같습니다 (편집기에서 빨리 시도해 보았습니다). 도서관/언어에 따라 첫 번째 부분은 여전히 ​​잘못된 버전 번호 내에서 "*"와 일치 할 수 있습니다. 1 년 동안 Regexp를 사용하지 않았기 때문에 뭔가 빠졌을 수 있습니다.

올바른 버전 번호 만 찾을 수 있어야합니다.

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

편집 : 실제로 그렉은 이미 그들을 추가하고 심지어 그의 솔루션을 개선했습니다. 나는 너무 느립니다 :)

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

첫 6 가지 예와 정확히 일치하고 다른 4 가지 예를 거부

  • 그룹 1 : major 또는 major.minor 또는 '*'
  • 존재하는 경우 그룹 2 : 부 또는 *
  • 존재하는 경우 그룹 3 : *

'(? ms)'를 제거 할 수 있습니다
이 정규 표현식에 QuickRex

2
VonC

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
Emmerson

이것은 1.2.3. * 와도 일치합니다

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

덜 우아하게 제안합니다.

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

2
Victor

좋은 연습으로 이것을 취합니다- vparse , 간단한 기능을 가진 tiny source

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
vitaly-t

하나 더 해결책 :

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