У меня есть номер версии следующего вида:
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
Может ли кто-нибудь предоставить мне не слишком сложное регулярное выражение для проверки и получения номеров выпуска, версии и модификации?
regex
versioning
Эндрю Борли
источник
источник
Ответы:
Я бы выразил формат как:
В качестве регулярного выражения это:
[Отредактируйте, чтобы добавить: это решение - краткий способ проверки, но было указано, что извлечение значений требует дополнительной работы. Решать ли это за счет усложнения регулярного выражения или за счет обработки согласованных групп - дело вкуса.
В моем решении группы захватывают
"."
персонажей. С этим можно справиться с использованием групп без захвата, как в ответе ajborley.Кроме того, самая правая группа захватит последний компонент, даже если их меньше трех, и поэтому, например, двухкомпонентный ввод приводит к захвату первой и последней групп, а средний - неопределенному. Я думаю, что с этим могут справиться не жадные группы, если они поддерживаются.
Код Perl для решения обеих проблем после регулярного выражения может быть примерно таким:
@version = (); @groups = ($1, $2, $3); foreach (@groups) { next if !defined; s/\.//; push @version, $_; } ($major, $minor, $mod) = (@version, "*", "*");
Что на самом деле не короче, чем разделение на
"."
]источник
Используйте регулярное выражение, и теперь у вас есть две проблемы. Я бы разделил это на точки («.»), А затем убедился, что каждая часть представляет собой либо подстановочный знак, либо набор цифр (регулярное выражение сейчас идеально). Если это действительно так, вы просто возвращаете правильный кусок разбиения.
источник
Это может сработать:
^(\*|\d+(\.\d+){0,2}(\.\*)?)$
На верхнем уровне «*» - это особый случай допустимого номера версии. В противном случае он начинается с числа. Затем идет ноль, одна или две последовательности «.nn», за которыми следует необязательный «. *». Это регулярное выражение будет принимать 1.2.3. *, Что может быть или не разрешено в вашем приложении.
Код для получения согласованных последовательностей, особенно
(\.\d+){0,2}
части, будет зависеть от вашей конкретной библиотеки регулярных выражений.источник
Спасибо за все ответы! Это туз :)
Основываясь на ответе OneByOne (который мне показался наиболее простым), я добавил несколько групп без захвата (части '(?:' - спасибо VonC за представление меня в группы без захвата!), Так что группы, которые захватывают только содержат цифры или символ *.
^(?:(\d+)\.)?(?:(\d+)\.)?(\*|\d+)$
Всем большое спасибо!
источник
(\*|\d+)
не первая^(?:(\d+)\.)?
группа.Мои 2 цента: у меня был такой сценарий: мне приходилось разбирать номера версий из строкового литерала. (Я знаю, что это очень отличается от исходного вопроса, но поиск в Google, чтобы найти регулярное выражение для анализа номера версии, показал этот поток вверху, поэтому добавив этот ответ здесь)
Таким образом, строковый литерал будет выглядеть примерно так: «Служба версии 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 }
источник
X.Y.Z
( т.е. ровно три части), где X и Y должны быть неотрицательными целыми числами, а не дополнительные ведущие нули. См. Semver.org .Не знаю, на какой платформе вы работаете, но в .NET есть класс System.Version, который будет анализировать номера версий «nnnn» за вас.
источник
Я склонен согласиться с раздельным предложением.
Я создал "тестера" для вашей проблемы на perl
#!/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 ------------------------
источник
^(?:(\d+)\.)?(?:(\d+)\.)?(\*|\d+)$
Возможно, более лаконичным было бы:
^(?:(\d+)\.){0,2}(\*|\d+)$
Затем его можно расширить до 1.2.3.4.5. * Или ограничить точно до XYZ, используя * или {2} вместо {0,2}
источник
Это должно работать для того, что вы оговорили. Он зависит от позиции подстановочного знака и представляет собой вложенное регулярное выражение:
^((\*)|([0-9]+(\.((\*)|([0-9]+(\.((\*)|([0-9]+)))?)))?))$
источник
Я видел много ответов, но ... у меня есть новый. По крайней мере, у меня это работает. Я добавил новое ограничение. Номера версий (старшие, второстепенные или патч) не могут начинаться с нуля, за которым следуют другие.
^(?:(0\\.|([1-9]+\\d*)\\.))+(?:(0\\.|([1-9]+\\d*)\\.))+((0|([1-9]+\\d*)))$
Он основан на предыдущем. Но я лучше вижу это решение ... для меня;)
Наслаждаться!!!
источник
Еще одна попытка:
Это дает три части в группах 4,5,6 НО: Они выровнены по правому краю. Таким образом, первое ненулевое значение из 4,5 или 6 дает поле версии.
источник
У меня было требование искать / сопоставлять номера версий в соответствии с соглашением maven или даже с одной цифрой. Но не в любом случае. Это было странно, мне потребовалось время, и я придумал это:
'^[0-9][0-9.]*$'
Это гарантирует, что версия,
Одним из недостатков является то, что версия может даже заканчиваться на '.' Но он может обрабатывать неограниченную длину версии (сумасшедшее управление версиями, если вы хотите это так называть)
Матчи:
Если вы не недовольны "." окончание, может быть, вы можете объединить концы с логикой
источник
(\d+)(.\d+)*
(?ms)^((?:\d+(?!\.\*)\.)+)(\d+)?(\.\*)?$|^(\d+)\.\*$|^(\*|\d+)$
Точно соответствует вашим 6 первым примерам и отвергает 4 других
Вы можете удалить '(? Ms)'.
Я использовал его, чтобы указать, что это регулярное выражение будет применяться к многострочным через QuickRex
источник
Это тоже соответствует 1.2.3. *
Я бы предложил менее элегантный:
(* | \ d + (. \ d +)? (. *)?) | \ d +. \ d +. \ d +)
источник
Имейте в виду, что регулярные выражения являются жадными, поэтому, если вы просто ищете в строке номера версии, а не в большом тексте, используйте ^ и $, чтобы отметить начало и конец вашей строки. Регулярное выражение от Грега, похоже, работает нормально (просто попробовал его в моем редакторе), но в зависимости от вашей библиотеки / языка первая часть может соответствовать «*» в неправильных номерах версий. Возможно, мне что-то не хватает, потому что я не использовал Regexp около года.
Это должно гарантировать, что вы сможете найти только правильные номера версий:
^ (\ * | \ d + (\. \ d +) * (\. \ *)?) $
edit: на самом деле Грег уже добавил их и даже улучшил свое решение, я слишком медленный :)
источник
Кажется, довольно сложно иметь регулярное выражение, которое делает именно то, что вы хотите (т. Е. Принимает только те случаи, которые вам нужны, и отклоняет все остальные и возвращает некоторые группы для трех компонентов). Я попробовал и придумал следующее:
^(\*|(\d+(\.(\d+(\.(\d+|\*))?|\*))?))$
IMO (я не тестировал широко), это должно нормально работать в качестве валидатора для ввода, но проблема в том, что это регулярное выражение не предлагает способ получения компонентов. Для этого вам все равно нужно разделить период.
Это решение не является универсальным, но в большинстве случаев при программировании этого не требуется. Конечно, это зависит от других ограничений, которые могут быть в вашем коде.
источник
Указание элементов 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>
источник
Я считаю это хорошим упражнением - 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; }
источник
Для разбора номеров версий, которые следуют следующим правилам: - Только цифры и точки - Не могут начинаться или заканчиваться точкой - Не могут быть двумя точками вместе
Это помогло мне.
^(\d+)((\.{1}\d+)*)(\.{0})$
Допустимые случаи:
1, 0.1, 1.2.1
источник
Еще одно решение:
^[1-9][\d]*(.[1-9][\d]*)*(.\*)?|\*$
источник
Иногда номера версий могут содержать второстепенную буквенно-цифровую информацию (например, 1.2.0b или 1.2.0-beta ). В этом случае я использую это регулярное выражение:
([0-9]{1,4}(\.[0-9a-z]{1,6}){1,5})
источник
Я нашел это, и у меня это работает:
источник