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

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

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

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



답변

형식을 다음과 같이 표현하겠습니다.

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

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

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

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

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

또한 가장 오른쪽 그룹은 세 개 미만의 구성 요소가 있더라도 마지막 구성 요소를 캡처하므로 예를 들어 두 구성 요소 입력은 첫 번째 및 마지막 그룹이 캡처되고 중간 그룹은 정의되지 않습니다. 나는 욕심이없는 그룹이 지원을 받으면 처리 할 수 ​​있다고 생각합니다.

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

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

쪼개지는 것보다 더 짧지는 않네요 "."
]


답변

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


답변

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

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

최상위 수준에서 “*”는 유효한 버전 번호의 특별한 경우입니다. 그렇지 않으면 숫자로 시작합니다. 그런 다음 0 개, 1 개 또는 2 개의 “.nn”시퀀스가 있고 그 뒤에 선택적 “. *”가 있습니다. 이 정규식은 응용 프로그램에서 허용되거나 허용되지 않을 수있는 1.2.3. *을 허용합니다.

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


답변

모든 응답에 감사드립니다! 에이스입니다 🙂

OneByOne의 답변 (가장 간단 해 보임)을 기반으로 일부 비 캡처 그룹 ( ‘(? :’부분-비 캡처 그룹을 소개 해준 VonC 덕분에!)을 추가했습니다. 숫자 또는 * 문자를 포함합니다.

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

모두에게 감사합니다!


답변

내 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        
}


답변

어떤 플랫폼을 사용하고 있는지 모르지만 .NET에는 “nnnn”버전 번호를 구문 분석하는 System.Version 클래스가 있습니다.


답변

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

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

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