Bash में मल्टी-डिजिट वर्जन नंबरों की तुलना करें


4

एक स्क्रिप्ट लिखने की कोशिश करना जो एप्लिकेशन के संस्करण की खोज करता है और फिर मूल्य लौटाता है। मेरी समस्या यह है कि मूल्य तीन से चार अंतराल लंबा है (उदाहरण 4.3.2)।

मैंने कुछ समय के लिए खोज की है और आपको कोई भी वाक्यविन्यास नहीं मिल सकता है जो आपको इसमें किसी भी संख्या के लिए एक =! या -ge का उपयोग करने की अनुमति देगा जिसमें इसमें अवधियों की संख्या अधिक होगी। बस सोच रहा था कि किसी के पास एक बेहतर तरीका है या मैं बस हर संस्करण को जारी करने के लिए जोड़ रहा हूं।

मैं क्या चाहता हूँ

else if [ $version1 -ge "9.0.8" ]; then

अब कैसे लिखा जाता है

vercheck=`mdls -name kMDItemVersion /Applications/iMovie.app`
version=`echo ${vercheck:17}`
version1=`echo ${version:1:5}`

[...]

else if [ $version1 = "9.0.8" ]; [ $version1 = "9.1.1" ]; then
    echo "You already have this version or a higher version installed"
    exit 0


जब तक मैं किसी चीज़ की गलतफहमी नहीं समझ लेता, तब तक समाधान मैटटेको अधिक जटिल लगता है। मैंने नीचे एक छोटा समाधान पोस्ट किया है।
टीजे लुओमा

BTW mdls -raw -name kMDItemVersion /Applications/iMovie.appआपको सुपरफ्लस सामान के बिना सिर्फ वर्जन नंबर देगा।
TJ लुओमा

जवाबों:


1

मेरा मानना ​​है कि मैंने इसे http://bashscripts.org/forum/viewtopic.php?f=16&t=1248 से थोड़ा अनुकूलित किया । मुझे यह पसंद है क्योंकि यह काफी कॉम्पैक्ट और पठनीय है।

यह वैकल्पिक, लेकिन वांछनीय IMO है:

if [ "$#" != "2" ]
then
    echo "$0 requires exactly two arguments."
    exit 2
fi

यहाँ मांस है:

मैं हमेशा $1"स्थानीय रूप से इंस्टॉल किए गए संस्करण" के लिए उपयोग करता हूं और $2"संस्करण की तुलना मैं" के खिलाफ कर रहा हूं, इसलिए यदि यह मुझे छोड़ देता है तो मुझे $? = 1अपडेट करने की आवश्यकता है, अन्यथा मैं अद्यतित हूं (या आगे भी):

function version { echo "$@" | awk -F. '{ printf("%d%03d%03d%03d\n", $1,$2,$3,$4); }'; }

if [ $(version $1) -gt $(version $2) ]; then
    echo "$1 is newer than $2"
    exit 0
elif [ $(version $1) -lt $(version $2) ]; then
    echo "$1 is older than $2"
    exit 1
else
    echo "$1 is identical to $2"
    exit 0
fi

यदि आप सभी के बारे में परवाह करते थे कि क्या $1यह तारीख तक था (यानी, इसके बराबर या उससे अधिक है $2) तो आप इसे और भी सरल बना सकते हैं:

if [ $(version $1) -ge $(version $2) ]; then
    echo "No Newer Version Available"
    exit 0
fi

नीचे दिए गए किसी भी कोड को केवल तभी निष्पादित किया जाएगा जब कोई नया संस्करण उपलब्ध हो। अन्यथा स्क्रिप्ट उस बिंदु पर सफाई से बाहर निकल जाएगी।

ps: मैं यह / बिन / zsh नहीं / बिन / बैश में करता हूं, लेकिन मुझे नहीं लगता कि इस मामले में कोई फर्क पड़ता है।


0

दरअसल, वर्जन नंबरों की तुलना करना बहुत सीधा है (कम से कम जब तक वे कड़ाई से संख्यात्मक हैं) क्योंकि वे पदानुक्रमित रूप से बाएं से दाएं हैं। उसी क्रम में एक क्रमिक तुलना स्पष्ट परिणाम देगी।

निम्नलिखित बैश फ़ंक्शन 0 (सही) वापस आएगा यदि दो संस्करण संख्याएं समान नहीं हैं , तो 1 (झूठा) यदि वे हैं, जब तक कि चर $version_1और $version_2दोनों में केवल समय के आधार पर अलग-अलग अंकों के समूहों की एक मनमानी संख्या होती है:

function versions_not_equal {
    while [[ $version_1 != "0" || $version_2 != "0" ]]; do
        (( ${version_1%%.*} != ${version_2%%.*} )) && return 0
        [[ ${version_1} =~ "." ]] && version_1="${version_1#*.}" || version_1=0
        [[ ${version_2} =~ "." ]] && version_2="${version_2#*.}" || version_2=0
    done
    false
}

अन्य तुलनाओं को लागू करना, अधिक से अधिक या बराबर , अंकगणितीय मूल्यांकन (यानी (( ${version_1%%.*} >= "${version_2%%.*}" ))) के तुलना ऑपरेटर को बदलने के रूप में सरल है ।


0

मैं आपको "उदाहरण के लिए यदि चेक किया गया संस्करण मिनट और अधिकतम के बीच है" का एक लंबा उदाहरण दे सकता है और आप इसे अपनी आवश्यकताओं के लिए बदल सकते हैं सिर -1 / पूंछ -1 और काटने 1 चर:

min_ver="a-1.1.1"
max_ver="a-9.1.1"
check_ver="a-2.2.9"
if [ "$( echo -e "${min_ver}\\n${max_ver}\\n${check_ver}" | sort --sort=version | head -2 | tail -1)" == ${check_ver} ]
then
  echo YES - apply  ${check_ver}
fi

0

यहाँ एक और समाधान है कि:

  • के अलावा कोई बाहरी कमांड नहीं चलाता है tr
  • संस्करण स्ट्रिंग में भागों की संख्या पर कोई प्रतिबंध नहीं है
  • विभिन्न भागों के साथ संस्करण तार की तुलना कर सकते हैं

ध्यान दें कि यह सरणी चर का उपयोग करके बैश कोड है।

compare_versions()
{
    local v1=( $(echo "$1" | tr '.' ' ') )
    local v2=( $(echo "$2" | tr '.' ' ') )
    local len="$(max "${#v1[*]}" "${#v2[*]}")"
    for ((i=0; i<len; i++))
    do
        [ "${v1[i]:-0}" -gt "${v2[i]:-0}" ] && return 1
        [ "${v1[i]:-0}" -lt "${v2[i]:-0}" ] && return 2
    done
    return 0
}

फ़ंक्शन देता है:

  • यदि संस्करण समान हैं (btw: 1.2 == 1.2.0)
  • 1 यदि 1 संस्करण बड़ा / नया है
  • 2 यदि दूसरा संस्करण बड़ा / नया है

हालाँकि # 1 - इसके लिए एक अतिरिक्त फ़ंक्शन की आवश्यकता होती है (लेकिन फ़ंक्शन minवैसे भी होने के लिए काफी उपयोगी है):

min()
{
    local m="$1"
    for n in "$@"
    do
        [ "$n" -lt "$m" ] && m="$n"
    done
    echo "$m"
}

हालाँकि # 2 - यह अल्फा-न्यूमेरिक भागों के साथ संस्करण स्ट्रिंग्स की तुलना नहीं कर सकता है (हालांकि यह वास्तव में जोड़ना मुश्किल नहीं होगा)।


0

आप संस्करण की कमी की जाँच करने के लिए संस्करण CLI का उपयोग कर सकते हैं

$ version ">=1.0, <2.0" "1.7"
$ go version | version ">=1.9"

बैश स्क्रिप्ट उदाहरण:

#!/bin/bash

if `version -b ">=9.0.0" "$(gcc --version)"`; then
  echo "gcc version satisfies constraints >=9.0.0"
else
  echo "gcc version doesn't satisfies constraints >=9.0.0"
fi
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.