Есть ли способ сравнить такие строки в bash, например: 2.4.5
and 2.8
and 2.4.5.1
?
linux
bash
versioning
exabiche
источник
источник
bc
. Это текст, а не цифры.2.1 < 2.10
потерпит неудачу таким образом.Ответы:
Вот чистая версия Bash, которая не требует никаких внешних утилит:
Запустите тесты:
источник
Please don't use it for software or documentation, since it is incompatible with the GNU GPL
: / но +1 за отличный кодЕсли у вас есть coreutils-7 (в Ubuntu Karmic, но не в Jaunty), ваша
sort
команда должна иметь-V
опцию (сортировку версий), которую вы можете использовать для сравнения:источник
brew install coreutils
. Тогда вышеприведенное просто нужно изменить, чтобы использовать gsort.sort
не имеет-V
опции.printf
вместоecho -e
.sort
также имеет-C
или--check=silent
, так что вы можете написатьverlte() { printf '%s\n%s' "$1" "$2" | sort -C -V }
; и проверка строгого меньше, чем проще сделать какverlt() { ! verlte "$2" "$1" }
.Вероятно, не существует универсально правильного способа добиться этого. Если вы пытаетесь сравнить версии в системе пакетов Debian, попробуйте
dpkg --compare-versions <first> <relation> <second>.
источник
dpkg --compare-versions "1.0" "lt" "1.2"
означает 1,0 менее 1,2. Результат сравнения$?
-0
если true, так что вы можете использовать его сразу послеif
выписки.У сортировки GNU есть опция:
дает:
источник
echo -e "2.4.10\n2.4.9" | sort -n -t.
sort
не имеет-V
опции.printf '%s\n' "2.4.5" "2.8" "2.4.5.1" | sort -V
.coreutils 7+
.Хорошо, если вы знаете количество полей, которые вы можете использовать -kn, n и получить супер-простое решение
источник
-t
опция принимает только односимвольные вкладки ... в противном случае,2.4-r9
будет работать также. Какой позор: /-g
на-n
. Любая причина, почему бы не для этого примера? На сопроводительной записке ... чтобы выполнить сравнение типов "больше чем", вы можете проверить, совпадает ли желаемый тип с фактической сортировкой ... например,desired="1.9\n1.11"; actual="$(echo -e $desired |sort -t '.' -k 1,1 -k 2,2 -g)";
и затем проверитьif [ "$desired" = "$actual" ]
.Это не более 4 полей в версии.
источник
printf "%03d%03d%03d%03d" $(echo "$1" | tr '.' '\n' | head -n 4)
head -n
работать, я должен был перейти наtr '.' '\n'
tr
черезsed 's/\(^\| \)0\([0-9][0-9]*\)/\1\2/g'
которую позаботятся об этом (довольно неуклюже)Используется как таковой:
(из https://apple.stackexchange.com/a/123408/11374 )
источник
Вы можете рекурсивно разделить
.
и сравнить, как показано в следующем алгоритме, взятом отсюда . Возвращает 10, если версии совпадают, 11, если версия 1 больше версии 2, и 9 в противном случае.Источник
источник
если нужно узнать, какая версия ниже, чем другая, я подхожу к проверке
sort --version-sort
изменения порядка строк моей версии:источник
Я реализовал функцию, которая возвращает те же результаты, что и у Денниса Уильямсона, но использует меньше строк. Первоначально он выполняет проверку работоспособности, что приводит
1..0
к сбою его тестов (что, я бы сказал, должно быть так), но все остальные его тесты проходят с этим кодом:источник
Вот простая функция Bash, которая не использует никаких внешних команд. Это работает для строк версии, которые содержат до трех числовых частей - менее 3 тоже хорошо. Это может быть легко расширено для большего. Он реализует
=
,<
,<=
,>
,>=
, и!=
условия.Вот тест:
Подмножество результатов теста:
источник
V
- чистое решение bash, никаких внешних утилит не требуется.=
==
!=
<
<=
>
и>=
(лексикографический).1.5a < 1.5b
1.6 > 1.5b
if V 1.5 '<' 1.6; then ...
.<>
<>
Код объяснил
Строка 1 : определить локальные переменные:
a
,op
,b
- сравнение операндов и оператора, то есть, "3,6"> "3.5a".al
,bl
- буквы хвостаa
иb
, инициализированные к элементу хвоста, т. е. «6» и «5a».Строки 2, 3 : цифры слева от хвостовых элементов, поэтому остаются только буквы, если они есть, то есть "" и "a".
Строка 4 : Правильные отсекать буквы
a
иb
оставить только последовательность числовых элементов в качестве локальных переменныхai
иbi
, то есть, «3,6» и «3,5». Известный пример: "4.01-RC2"> "4.01-RC1" дает ai = "4.01" al = "- RC2" и bi = "4.01" bl = "- RC1".Строка 6 : Определите локальные переменные:
ap
,bp
- нулевой правой отступы дляai
иbi
. Начните с сохранения только точек между элементами, число которых равно количеству элементовa
иb
соответственно.Строка 7 : Затем добавьте «0» после каждой точки, чтобы создать дополнительные маски.
Строка 9 : локальные переменные:
w
- ширина изделияfmt
- строка формата printf, рассчитываетсяx
- временныйIFS=.
Баш расщепляется значения переменных на «».Строка 10 : Расчет
w
максимальной ширины элемента, которая будет использоваться для выравнивания элементов для лексикографического сравнения. В нашем примере w = 2.Строка 11 : Создание формата выравнивания PRINTF путем замены каждого символа
$a.$b
с%${w}s
, то есть, "3.6"> "3.5A" доходность "% 2s% 2s% 2s% 2s".Строка 12 : «printf -v a» устанавливает значение переменной
a
. Это эквивалентноa=sprintf(...)
во многих языках программирования. Обратите внимание, что здесь, благодаря эффекту IFS =. аргументыprintf
разбить на отдельные элементы.С первыми
printf
элементамиa
слева добавляются пробелы, в то время как к ним добавляется достаточное количество элементов «0»,bp
чтобы гарантировать, что результирующая строкаa
может быть осмысленно сопоставлена с аналогичным форматированиемb
.Обратите внимание , что мы добавляем
bp
- неap
кai
потомуap
иbp
могут иметь различные длины, так что это приводитa
иb
имеющие одинаковую длину.Со вторым
printf
мы добавляем букву часть ,al
чтобыa
с достаточной прокладкой для обеспечения эффективного сравнения. Теперьa
готов для сравнения сb
.Строка 13 : то же, что строка 12, но для
b
.Строка 15 : Разделение случаев сравнения между не встроенными (
<=
и>=
) и встроенными операторами.Строка 16 : если оператором сравнения является
<=
тест дляa<b or a=b
- соответственно>=
a<b or a=b
Строка 17 : тест для встроенных операторов сравнения.
<>
источник
Я использую встроенный Linux (Yocto) с BusyBox. BusyBox
sort
не имеет-V
опции (но BusyBoxexpr match
может делать регулярные выражения). Поэтому мне нужно было сравнить версию Bash, которая работала с этим ограничением.Я сделал следующее (аналогично ответу Денниса Уильямсона ), чтобы сравнить, используя алгоритм «естественной сортировки». Он разбивает строку на числовые и нечисловые части; он сравнивает числовые части численно (то
10
есть больше, чем9
) и сравнивает нечисловые части как простое сравнение ASCII.Он может сравнивать более сложные номера версий, такие как
1.2-r3
против1.2-r4
1.2rc3
против1.2r4
Обратите внимание, что он не возвращает тот же результат для некоторых угловых случаев в ответе Денниса Уильямсона . В частности:
Но это угловые случаи, и я думаю, что результаты все еще разумны.
источник
источник
--check=silent
без необходимости использоватьtest
следующее:if printf '%s\n%s' 4.2.0 "$OVFTOOL_VERSION" | sort --version-sort -C
Это тоже
pure bash
решение, так как printf - это встроенный bash.источник
Для старой версии / busybox
sort
. Простая форма обеспечивает приблизительный результат и часто работает.Это особенно полезно в версии, которая содержит буквенные символы, такие как
источник
Как насчет этого? Кажется работать?
источник
Вот еще одно решение bash без каких-либо внешних вызовов:
И есть еще более простое решение, если вы уверены, что рассматриваемые версии не содержат начальных нулей после первой точки:
Это будет работать для чего-то вроде 1.2.3 против 1.3.1 против 0.9.7, но не будет работать с 1.2.3 против 1.2.3.0 или 1.01.1 против 1.1.1
источник
4.4.4 > 44.3
Вот уточнение верхнего ответа (ответа Денниса), который является более кратким и использует другую схему возвращаемых значений, чтобы упростить реализацию <= и> = с помощью одного сравнения. Он также сравнивает все после первого символа, а не в [0-9.] Лексикографически, поэтому 1.0rc1 <1.0rc2.
источник
Я реализовал еще одну функцию сравнения. У этого было два специфических требования: (i) я не хотел, чтобы функция потерпела неудачу при использовании,
return 1
ноecho
вместо этого; (ii) поскольку мы получаем версии из репозитория git, версия "1.0" должна быть больше, чем "1.0.2", что означает, что "1.0" происходит из транка.Не стесняйтесь комментировать и предлагать улучшения.
источник
Вы можете использовать версию CLI для проверки ограничений версии
Пример сценария Bash:
источник
Я наткнулся и решил эту проблему, чтобы добавить дополнительный (и более короткий и простой) ответ ...
Первое замечание: расширенное сравнение оболочки не удалось, как вы уже знаете ...
Используя сортировку -t '.'- g (или сортировку -V, как упомянуто kanaka) для упорядочивания версий и простого сравнения строк bash, я нашел решение. Входной файл содержит версии в столбцах 3 и 4, которые я хочу сравнить. Это перебирает список, определяющий совпадение, или если один больше другого. Надеюсь, что это может помочь любому, кто хочет сделать это, используя bash настолько просто, насколько это возможно.
Спасибо блогу Барри за идею сортировки ... ref: http://bkhome.org/blog/?viewDetailed=02199
источник
Это довольно просто и мало.
источник
echo -ne "$1\n$2"
наprintf '%s\n ' "$1" "$2"
. Также лучше использовать$()
вместо спинок.Благодаря решению Денниса мы можем расширить его, чтобы разрешить операторы сравнения '>', '<', '=', '==', '<=' и '> ='.
Затем мы можем использовать операторы сравнения в выражениях, таких как:
и проверить только значение true / false результата, например:
источник
Вот еще одна версия Bash, немного меньше принятого ответа. Он только проверяет, является ли версия меньше или равна «минимальной версии», и проверяет буквенно-цифровые последовательности лексикографически, что часто дает неправильный результат («снимок» не позднее, чем «выпуск», чтобы дать общий пример) , Это будет хорошо работать для основных / второстепенных.
источник
Другой подход (модифицированная версия @joynes), который сравнивает точечные версии, как задано в вопросе
(т. Е. «1.2», «2.3.4», «1.0», «1.10.1» и т. Д.).
Максимальное количество позиций должно быть известно заранее. Подход предполагает максимум 3 варианта позиции.
пример использования:
возвращает: 1, поскольку 1.10.1 больше 1,7
возвращает: 0, поскольку 1.10.1 ниже 1.11
источник
Вот чистое решение Bash, которое поддерживает ревизии (например, «1.0-r1»), основываясь на ответе, опубликованном Деннисом Уильямсоном . Его можно легко изменить, чтобы он поддерживал такие вещи, как -RC1, или извлекал версию из более сложной строки, изменяя регулярное выражение.
Для получения подробной информации о реализации, пожалуйста, обратитесь к комментариям внутри кода и / или включите включенный код отладки:
источник
Ого ... это далеко внизу списка старых вопросов, но я думаю, что это довольно элегантный ответ. Сначала преобразуйте каждую разделенную точками версию в свой собственный массив, используя расширение параметров оболочки (см. Расширение параметров оболочки ).
Теперь эти два массива имеют номер версии в виде числовой строки в порядке приоритета. Многие из приведенных выше решений ведут вас оттуда, но все это вытекает из наблюдения, что строка версии - это просто целое число с произвольным основанием. Мы можем проверить нахождение первой неравной цифры (как это делает strcmp для символов в строке).
Это отражает отрицательное число, если первая версия меньше, чем вторая, ноль, если они равны, и положительное число, если первая версия больше. Некоторый вывод:
Вырожденные случаи, такие как «.2» или «3.0». не работают (неопределенные результаты), и если рядом с '.' присутствуют нечисловые символы он может потерпеть неудачу (не проверял), но определенно будет неопределенным. Так что это должно быть связано с функцией очистки или соответствующей проверкой правильности форматирования. Кроме того, я уверен, что с некоторыми изменениями, это может быть сделано более надежным без чрезмерного багажа.
источник
Кредит идет на @Shellman
источник