Проверка правильности номера версии с помощью Perl - PullRequest
1 голос
/ 14 мая 2009

Я борюсь с проверкой правильности номеров версий в Perl. Правильный номер версии выглядит так:

  • Начинается с v или ver,
  • После этого число, если оно равно 0, тогда никакие другие числа не допускаются в этой части (например, 10, 3993 и 0 в порядке, 01 - нет),
  • После этого полная остановка, число, полная остановка, номер, полная остановка и номер.

т.е. действительный номер версии может выглядеть примерно так: v0.123.45.678 или ver18.493.039.1.

Я придумал следующее регулярное выражение:

if ($ver_string !~ m/^v(er)?(0{1}\.)|([1-9]+\d*\.)\d+\.\d+\.\d+/) 
{
   #print error
}

Но это не работает, потому что принят номер версии, такой как verer01.34.56.78. Я не могу этого понять, я знаю, что Perl имеет тенденцию быть жадным, но разве не должно ^ v (er)? убедиться, что может быть максимум один "эр"? И почему нет 0 {1}. соответствует только «0», вместо принятия «01». как хорошо?

Это регулярное выражение на самом деле поймало вещь "rere": m / ^ v (er)? [0-9.] + /, Но я не вижу, где я позволю это сделать в моей попытке.

Ответы [ 3 ]

7 голосов
/ 14 мая 2009

Ваша проблема в том, что или - | - который вы используете, разделяет весь шаблон на две части. | будет заключаться в скобки или конец выражения, а не только в два соседних элемента.

Вам нужно поставить несколько дополнительных скобок, чтобы показать, какую часть выражения вы хотите или отредактировали. Поэтому первым шагом к исправлению вашего паттерна будет:

^v(er)?((0{1}\.)|([1-9]+\d*\.))\d+\.\d+\.\d+

Вы также хотите поставить $ в конце, чтобы убедиться, что в конце номера версии нет ложных символов.

Кроме того, указывать {1} не нужно, поскольку это означает, что предыдущий элемент ровно один раз, что является значением по умолчанию. Однако вы можете использовать {3} в конце вашего паттерна, так как вам нужны три группы цифр в конце.

Точно так же вам не нужно + после [1-9], так как другие цифры будут захвачены \d*.

И мы можем также снять лишние скобки.

Таким образом, вы можете упростить ваш шаблон до следующего:

^v(er)?(0|[1-9]\d*)(.\d+){3}$
1 голос
/ 14 мая 2009

Вы можете сделать это с одним регулярным выражением, или вы можете сделать это в 2 шага, второй шаг - проверить, что первое число не начинается с 0.

Кстати, я склонен использовать [0-9] вместо \ d для чисел, есть много символов, которые классифицируются как числа в стандарте Unicode (и, следовательно, в Perl), с которыми вы, возможно, не захотите иметь дело.

Вот пример кода, подпрограмма version_ok - это то, где все происходит.

#!/usr/bin/perl

use strict;
use warnings;

use Test::More tests => 7;

while( <DATA>) 
  { chomp; 
    my( $version, $expected)= split /\s*=>\s*/;
    is( version_ok( $version), $expected, $version);
  }

sub version_ok  
  { my( $version)=@_;
    if( $version=~ m{^v(?:er)?        # starts with v or ver
                      ([0-9]+)        # the first number
                      (?:\.[0-9]+){3} # 3 times dot number
                     $}x)             # end
      { if( $1 =~ m{^0[0-9]})         
          { return 0; }               # no good: first number starts with 0
        else 
          { return 1; } 
      } 
    else
      { return 0; }
  }


__DATA__
v0.123.45.678      => 1
ver18.493.039.1    => 1
verer01.34.56.78   => 0
v01.5.5.5          => 0
ver101.5.5.5       => 1
ver101.5.5.        => 0
ver101.5.5         => 0
0 голосов
/ 14 мая 2009

Регулярное выражение может работать для ваших тестовых случаев, но модуль CPAN Perl :: Version может показаться лучшим вариантом с двумя оговорками:

  • сам не пробовал
  • похоже, что последний выпуск модуля был в 2007 году, что делает его рекурсивной проблемой
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...