Wie vergleiche ich die Version eines Programms in einem Shell-Skript?

13

Angenommen, ich möchte die gccVersion vergleichen , um festzustellen, ob auf dem System die Mindestversion installiert ist oder nicht.

Um die gccVersion zu überprüfen , habe ich Folgendes ausgeführt

gcc --version | head -n1 | cut -d" " -f4

Die Ausgabe war

4.8.5

Also schrieb ich eine einfache ifAnweisung, um diese Version mit einem anderen Wert zu vergleichen

if [ "$(gcc --version | head -n1 | cut -d" " -f4)" -lt 5.0.0 ]; then
    echo "Less than 5.0.0"
else
    echo "Greater than 5.0.0"
fi

Aber es wirft einen Fehler:

[: integer expression expected: 4.8.5

Ich habe meinen Fehler verstanden, dass ich zum Vergleichen Zeichenfolgen verwendet habe und die -lterforderliche Ganzzahl. Gibt es eine andere Möglichkeit, die Versionen zu vergleichen?

Abhimanyu Saharan
quelle
@ 123 Nichts passiert
Abhimanyu Saharan
1
Es gibt auch eine Stapelüberlauf-Frage mit einer Reihe verschiedener Vorschläge zum Vergleichen von Versionszeichenfolgen.
29.
1
Viel einfacher als die Verwendung von Rohren:gcc -dumpversion
Victor Lamoine

Antworten:

20

Ich weiß nicht, ob es schön ist, aber es funktioniert für jedes mir bekannte Versionsformat.

#!/bin/bash
currentver="$(gcc -dumpversion)"
requiredver="5.0.0"
 if [ "$(printf '%s\n' "$requiredver" "$currentver" | sort -V | head -n1)" = "$requiredver" ]; then 
        echo "Greater than or equal to 5.0.0"
 else
        echo "Less than 5.0.0"
 fi

( Hinweis: Bessere Version des Benutzers 'Wildcard': /unix//users/135943/wildcard , zusätzliche Bedingung entfernt)

Luciano Andress Martini
quelle
3
Zuerst fand ich das schrecklich, und dann wurde mir klar, dass die Schönheit des Shell-Scripting genau darin besteht, solche Werkzeuge zu missbrauchen. +1
Boykott SE für Monica Cellio
2
Dies wird unterbrochen, wenn die print-Anweisung '%'-Zeichen enthält. Bessere ersetzen printf "$requiredver\n$currentver"mit printf '%s\n' "$requiredver" "$currentver".
Phk
1
-Vist eine GNU-Erweiterung von sort(1)daher ist diese Lösung nicht portabel.
stefanct
1
sort -nfunktioniert bei numerischen Versionen fast genauso.
Rockallite
1
@ LucianoAndressMartini, sehen Sie, was Sie von meiner Bearbeitung halten.
Wildcard
2

Hier gebe ich eine Lösung zum Vergleichen von Unix-Kernel-Versionen. Und es sollte für andere wie gcc funktionieren. Ich kümmere mich nur um die ersten 2 Versionsnummern, aber Sie können eine weitere Logikebene hinzufügen. Es ist ein Liner und ich habe es zum besseren Verständnis in mehreren Zeilen geschrieben.

check_linux_version() {
    version_good=$(uname -r | awk 'BEGIN{ FS="."}; 
    { if ($1 < 4) { print "N"; } 
      else if ($1 == 4) { 
          if ($2 < 4) { print "N"; } 
          else { print "Y"; } 
      } 
      else { print "Y"; }
    }')

    #if [ "$current" \< "$expected" ]; then
    if [ "$version_good" = "N" ]; then
        current=$(uname -r)
        echo current linux version too low
        echo current Linux: $current
        echo required 4.4 minimum
        return 1
    fi
}

Sie können dies ändern und zur Überprüfung der gcc-Version verwenden.

Kemin Zhou
quelle
+1 ist es kompatibel mit anderen Unix-ähnlichen? (Meine Lösung ist nicht)
Luciano Andress Martini
1

Kürzere Version:

version_greater_equal()
{
    printf '%s\n%s\n' "$2" "$1" | sort -V -C
}

version_greater_equal "${gcc_version}" 8.2 || die "need 8.2 or above"
März
quelle
(1) Dies ist eine geringfügige Abweichung von bereits gegebenen Antworten. Sie können einen Mehrwert schaffen, indem Sie eine Erklärung hinzufügen, die noch nicht veröffentlicht wurde. (2)  printf '%s\n'ist gut genug; printfwiederholt die Formatzeichenfolge nach Bedarf.
G-Man sagt 'Reinstate Monica'
Normalerweise bevorzuge ich das Bearbeiten vorhandener Antworten, aber das Löschen der Hälfte davon ist schwierig: Andere sehen möglicherweise einen Wert, wo ich ihn nicht sehe. Gleiches gilt für ausführliche Erklärungen. Weniger ist mehr.
MarcH
Ich weiß, dass die printfFormatzeichenfolge wiederholt wird, aber ich (die fehlende!) Syntax dafür ist meiner Meinung nach dunkel; Daher verwende ich dies nur bei Bedarf = wenn die Anzahl der Argumente groß oder variabel ist.
MarcH
1
function version_compare () {
  function sub_ver () {
    local len=${#1}
    temp=${1%%"."*} && indexOf=`echo ${1%%"."*} | echo ${#temp}`
    echo -e "${1:0:indexOf}"
  }
  function cut_dot () {
    local offset=${#1}
    local length=${#2}
    echo -e "${2:((++offset)):length}"
  }
  if [ -z "$1" ] || [ -z "$2" ]; then
    echo "=" && exit 0
  fi
  local v1=`echo -e "${1}" | tr -d '[[:space:]]'`
  local v2=`echo -e "${2}" | tr -d '[[:space:]]'`
  local v1_sub=`sub_ver $v1`
  local v2_sub=`sub_ver $v2`
  if (( v1_sub > v2_sub )); then
    echo ">"
  elif (( v1_sub < v2_sub )); then
    echo "<"
  else
    version_compare `cut_dot $v1_sub $v1` `cut_dot $v2_sub $v2`
  fi
}

### Usage:

version_compare "1.2.3" "1.2.4"
# Output: <

Gutschrift geht an @Shellman

Xaqron
quelle
0

Früher haben wir viele Versionsprüfungen in einem GNU-Makefile durchgeführt. Wir haben durch die Makefile-Einrichtungen geschossen. Wir mussten alte Binutils und Buggy-Compiler erkennen und sie im Handumdrehen umgehen.

Das Muster, das wir verwendeten, war:

#!/usr/bin/env bash

CC=$(command -v gcc)
GREP=$(command -v grep)

# Fixup CC and GREP as needed. It may be needed on AIX, BSDs, and Solaris
if [[ -f "/usr/gnu/bin/grep" ]]; then
    GREP="/usr/gnu/bin/grep"
elif [[ -f "/usr/linux/bin/grep" ]]; then
    GREP="/usr/linux/bin/grep"
elif [[ -f "/usr/xpg4/bin/grep" ]]; then
    GREP="/usr/xpg4/bin/grep"
fi

# Check compiler for GCC 4.8 or later
GCC48_OR_LATER=$("$CXX" -v 2>&1 | "$GREP" -i -c -E "gcc version (4\.[8-9]|[5-9]\.)")
if [[ "$GCC48_OR_LATER" -ne 0 ]];
then
   ...
fi

# Check assembler for GAS 2.19 or later
GAS219_OR_LATER=$("$CXX" -xc -c /dev/null -Wa,-v -o/dev/null 2>&1 | "$GREP" -c -E "GNU assembler version (2\.19|2\.[2-9]|[3-9])")
if [[ "$GAS219_OR_LATER" -ne 0 ]];
then
   ...
fi

quelle