जांचें कि क्या बैश संस्करण है> = दिया गया संस्करण संख्या


12

मुझे परीक्षण करने की आवश्यकता है यदि बैश संस्करण संख्या> = एक विशिष्ट संख्या के लिए है। उदाहरण के लिए मेरे पास:

$ bash --version
GNU bash, version 4.3.48(1)-release (x86_64-pc-linux-gnu)
Copyright (C) 2013 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>

This is free software; you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.

साहचर्य सरणियों का उपयोग करने के लिए बैश संस्करण संख्या> = 4 होनी चाहिए।

मेरी बैश स्क्रिप्ट में मैं एक एल-लाइनर परीक्षण को सबसे सुरुचिपूर्ण / कुशल / पठनीय तरीके से संभव करना चाहता हूं, लेकिन अन्य दृष्टिकोण भी स्वीकार किए जाते हैं।


क्या आपने चर $BASH_VERSIONऔर $BASH_VERSINFOचर को देखा है ?
स्टीलड्राइवर

@steeldriver No. यदि आप इसे पोस्ट करना चाहते हैं, तो bash विशिष्ट मामले में एक स्वीकार्य उत्तर होगा। हालाँकि अन्य मामलों के लिए पर्यावरण चर उपलब्ध नहीं हो सकते हैं।
विनयुनुच्स


@SergiyKolodyazhnyy जो केवल बैश से संबंधित है। हालाँकि मैं एक बैश वन-लाइनर या स्क्रिप्ट / फंक्शन की तलाश कर रहा हूँ, जो केवल bash संस्करण संख्या की जाँच कर रहा है, अंतिम लक्ष्य नहीं है। --versionआउटपुट को जोड़कर और परीक्षण करके सभी कार्यक्रमों की जांच करना एक सामान्य दिनचर्या का मूल उद्देश्य था। मैंने अपने अनुसार प्रश्न संपादित किया है।
विनयुनुच्स

संस्करण संख्या प्रारूप कार्यक्रमों में बेतहाशा भिन्न होते हैं। जिस तरह से वे संस्करण विवरण की रिपोर्ट करते हैं, वह भी बेतहाशा भिन्न होता है। यादृच्छिक प्रोग्राम के संस्करण की जांच करने का तरीका पूछने के लिए बस व्यावहारिक नहीं है। यह प्रश्न बहुत व्यापक है।
मूरू

जवाबों:


16

प्रयत्न:

$ [ "${BASH_VERSINFO:-0}" -ge 4 ] && echo "bash supports associative arrays"
bash supports associative arrays

BASH_VERSINFOएक पठनीय सरणी चर है जिसके सदस्य बैश के इस उदाहरण के लिए संस्करण जानकारी रखते हैं। चूँकि इसे bash 2.0 के साथ पेश किया गया था, इसलिए यह संभवतः सभी bash संस्करणों द्वारा समर्थित है, जिनका आप सामना करेंगे। लेकिन, सतर्क रहने के लिए, हम 0किसी भी पुराने संस्करण बैश के लिए एक डिफ़ॉल्ट मान शामिल करते हैं जिसके लिए यह चर अप्रभावित है।

अन्य कार्यक्रमों से संस्करण की जानकारी निकालना

आपने लिबरऑफिस, पायथन, कर्नेल, आदि के बारे में पूछा।

LibreOffice संस्करण जानकारी का उत्पादन करता है जो दिखता है:

$ libreoffice --version
LibreOffice 5.2.6.2 20m0(Build:2)

संस्करण संख्या निकालने के लिए:

$ libreoffice --version | cut -d' ' -f2
5.2.6.2

अजगर के लिए:

$ python -c 'import platform; print(platform.python_version())'
2.7.13

कर्नेल संस्करण प्राप्त करने के लिए, का उपयोग करें uname:

$ uname -r
4.9.0-2-amd64

शानदार जवाब! बस ध्यान दें कि आपका uname -r"4.9.0-2-amd64" है, जो नियमित रूप से बैश परीक्षण के साथ मेरा "4.11.1-041101-जेनेरिक" से अधिक परीक्षण कर सकता है जब वास्तव में मेरा संस्करण संख्या अधिक हो।
विनयुनुच्स

2
@ WinEunuuchs2Unix पायथन उपकरण संस्करण के तारों की सही तुलना कर सकते हैं। पायथन में संस्करण के तार की तुलना करें
wjandrea

जॉन-- अजगर उदाहरण को $ python --versionकिस रिटर्न के साथ छोटा किया जा सकता है Python 2.7.12। @ wjandrea-- लिंक +1 के लिए धन्यवाद। शायद मैं सभी प्रोग्राम नामों और न्यूनतम संस्करण संख्याओं की एक तालिका बना सकता हूं। फिर pythonआपके द्वारा प्रदान किए गए लिंक की संशोधित प्रतिलिपि के लिए तालिका पास करें । क्योंकि केवल संकलित पायथन को grubआपके द्वारा बुलाया जा सकता है, आपको लगता है कि ऐसा करने के लिए एक बाइनरी मौजूद है या शेल में संभव है।
विनयुनुच्स

9

संस्करण संख्याओं की तुलना करने के बजाय, आप सीधे फ़ीचर के लिए परीक्षण कर सकते हैं। declare -Aरिटर्न 2(कम से कम बाश 3.2 में) यदि यह पहचान नहीं करता है -A, तो उसके लिए परीक्षण करें (यह भी एक त्रुटि प्रिंट करता है):

unset assoc
if ! declare -A assoc ; then
    echo "associative arrays not supported!"
    exit 1
fi

( declare -A varयदि varयह एक गैर-सहयोगी सरणी है, तो unsetयह पहले विफल हो जाता है ।)

हालांकि मैं वास्तव में किसी को बैश में बैकपोर्ट सुविधाओं में नहीं जा रहा हूं, सामान्य तौर पर यह सुविधाओं के लिए जांच करने के लिए अधिक उपयुक्त है, न कि संस्करण। बाश के मामले में भी, कोई व्यक्ति केवल सीमित सुविधाओं वाले संस्करण को संकलित कर सकता है ...


संस्करण संख्याओं के परीक्षण के अधिक सामान्य मामले के दो भाग हैं: 1) परीक्षण करने के लिए सही संस्करण संख्या कैसे खोजनी है, और 2) दूसरे मूल्य के खिलाफ इसकी तुलना कैसे करें।

पहला सबसे कठिन है। कई प्रोग्राम अपने वर्जन नंबर को कमांड लाइन के झंडे के साथ --versionया जैसे बताते हैं -v, लेकिन आउटपुट फॉर्मेट बदलता रहता है और प्रोग्राम वर्जन को चुनना मुश्किल हो सकता है। फिर एक ही समय में एक ही प्रोग्राम के कई संस्करण स्थापित होने की समस्या है।

दूसरा संस्करण संख्याओं के प्रारूप के कुछ ज्ञान पर निर्भर करता है। डेबियन-शैली संस्करण संख्याओं कीdpkg तुलना कर सकते हैं (जो मुझे लगता है कि सबसेट के रूप में सेवर प्रकार के संस्करण शामिल हैं ):

if dpkg --compare-versions 4.3.30 ge 4.0.0 ; then
    echo "it's version 4.x"
fi

या, बस ऊपर गठबंधन करने के लिए:

bashver=$( bash --version | sed -Ee 's/GNU bash, version ([0-9.]+).*/\1/;q' )
if dpkg --compare-versions "$bashver" ge 4.0.0 ; then
    echo "'bash' in your path is version 4.x"
fi

5

वहाँ कुछ तरीके हैं जो आप प्राप्त करना चाहते हैं।

1. $ BASH_VERSION का उपयोग करें

यह देखने के लिए पर्याप्त है कि $BASH_VERSIONचर में क्या है । व्यक्तिगत रूप से मैं इस तरह से सबस्क्रिप्शन का उपयोग करूंगा:

$ (read -d "." version trash <<< $BASH_VERSION; echo "$version" )
4

ध्यान दें कि <<<यहाँ-डॉक के लिए सिंटैक्स पोर्टेबल नहीं है, अगर आप इसका उपयोग करने जा रहे हैं /bin/sh, जो उबंटू पर डैश है और एक अलग सिस्टम पर कुछ और हो सकता है

वैकल्पिक तरीका केस स्टेटमेंट या यदि स्टेटमेंट है। व्यक्तिगत रूप से, मैं यह करूँगा:

bash-4.3$ case $BASH_VERSION in 4.*) echo "Can use associative arrays";; ?) echo "can't use associative arrays" ;; esac
Can use associative arrays

संभवतः पोर्टेबिलिटी के लिए, आपको शायद यह जांचना चाहिए कि क्या ऐसा वैरिएबल पहली बार में किसी चीज़ के साथ सेट किया गया है [ -n $BASH_VERSION ]

यह पूरी तरह से एक स्क्रिप्ट में उपयोग किए जाने वाले फ़ंक्शन के रूप में फिर से लिखा जा सकता है। कुछ लंबी लाइनें:

#!/bin/bash
version_above_4(){
    # check if $BASH_VERSION is set at all
    [ -z $BASH_VERSION ] && return 1

    # If it's set, check the version
    case $BASH_VERSION in 
        4.*) return 0 ;;
        ?) return 1;; 
    esac
}

if version_above_4
then
    echo "Good"
else
    echo "No good"
fi

यह वन-लाइनर नहीं है, हालांकि यह बहुत बेहतर है। मात्रा से अधिक गुणवत्ता।

2. जांचें कि क्या स्थापित है

उसके लिए आपको इस apt-cache policyतरह के आउटपुट को फ़िल्टर करना होगा

$ apt-cache policy bash | awk -F '[:.]' '/Installed:/{printf "%s\n",substr($2,2)}'
4

dpkg-queryकुछ छानने के माध्यम से भी काम में आ सकता है awk

$ dpkg-query -W bash | awk '{print substr($2,1,1)}'   
4

ध्यान दें कि यह पोर्टेबल नहीं है, क्योंकि अगर कोई सिस्टम dpkgया aptइंस्टाल पर स्थापित नहीं है (उदाहरण के लिए, आरएचईएल या फ्रीबीएसडी), तो यह आपको कोई अच्छा काम नहीं देगा।

3. यदि कोई त्रुटि हो तो स्क्रिप्ट से बाहर निकलने के लिए सेट -e का उपयोग करें

इसके चारों ओर जाने का एक तरीका सिर्फ एक सहयोगी साहचर्य से आगे जाना है और जब bashउनका उपयोग नहीं किया जा सकता है तो उसे छोड़ दें। set -eनीचे लाइन #!/bin/bashहै, तो स्क्रिप्ट साहचर्य सरणी का उपयोग नहीं कर सकते हैं स्क्रिप्ट छोड़ने की अनुमति देगा।

इससे आपको उपयोगकर्ता को स्पष्ट रूप से बताने की आवश्यकता होगी: "अरे, आपको वास्तव में 4.3 या इसके बाद के संस्करण की आवश्यकता है, अन्यथा स्क्रिप्ट काम नहीं करेगी"। तब जिम्मेदारी उपयोगकर्ता के साथ रहती है, हालांकि कुछ लोग तर्क दे सकते हैं कि यह वास्तव में सॉफ्टवेयर विकास के लिए एक अच्छा दृष्टिकोण नहीं है।

4. सभी आशाओं का त्याग करें और पोर्टेबल, POSIX- अनुरूप स्क्रिप्ट लिखें

bashस्क्रिप्ट पोर्टेबल नहीं हैं क्योंकि इसका सिंटेक्स बॉर्न शेल के साथ संगत नहीं है। यदि आप जो स्क्रिप्ट लिख रहे हैं, वह केवल उबंटू ही नहीं, बल्कि विभिन्न प्रणालियों की एक श्रृंखला पर उपयोग होने वाली है, तो सभी आशाओं को छोड़ दें, और साहचर्य सरणियों के अलावा कुछ और उपयोग करने के तरीके खोजें। जिसमें दो एरेज़ या कॉन्फ़िगरेशन फ़ाइल पार्स करना शामिल हो सकता है। एक अलग भाषा, पर्ल या पायथन पर स्विच करने पर भी विचार करें, जहां वाक्यविन्यास कम से कम अधिक पोर्टेबल है bash


सहयोगी सरणी "दो सरणियों" का दूसरा भाग है जैसा कि आप अनुभाग 4 में सुझाव देते हैं। एकमात्र उद्देश्य "पथ / से / फ़ाइल-नाम" को पकड़ना है और मुख्य सरणी के भीतर मूल्य सूचकांक है। साहचर्य सरणी को नियमित अनुक्रमित सरणी में खोजों को गति देने के लिए बनाया गया था जो वर्तमान में अनुक्रमिक हैं। हालाँकि, मेरी नज़र पाइथन पर है, फिर भी, मेरी वर्तमान बैश संगतता उबंटू और शायद बैश पर विंडोज 10 के लिए केंद्रित है। मुझे आपकी स्क्रिप्ट पसंद है जिसे सिलवाया जा सकता है। उदाहरण के लिए yad --versionरिटर्न 0.37.0 (GTK+ 3.18.9)लेकिन नई सुविधाएँ वर्तमान में हैं 0.39
विनयुनुच्स

महान और उपयोगी जवाब। धन्यवाद!
कोडीनिन्जा

2

वन-लाइनर संभव नहीं है, लेकिन बैश स्क्रिप्ट संभव है

मैंने एक स्क्रिप्ट विकसित की है जो स्टैक ओवरफ्लो में उत्तर पर आकर्षित करती है। उन उत्तरों में से एक डीकेएमएस एप्लिकेशन के लिए 2004 में डेल कर्मचारी लेखन संस्करण संख्या तुलना के कारण हुआ।

कोड

नीचे दिए गए बैश स्क्रिप्ट को कमांड का उपयोग करके निष्पादन योग्य के रूप में चिह्नित करने की आवश्यकता है chmod a+x script-name। मैं नाम का उपयोग कर रहा हूं /usr/local/bin/testver:

#!/bin/bash

# NAME: testver
# PATH: /usr/local/bin
# DESC: Test a program's version number >= to passed version number
# DATE: May 21, 2017. Modified August 5, 2019.

# CALL: testver Program Version

# PARM: 1. Program - validated to be a command
#       2. Version - validated to be numberic

# NOTE: Extracting version number perl one-liner found here:
#       http://stackoverflow.com/questions/16817646/extract-version-number-from-a-string

#       Comparing two version numbers code found here:
#       http://stackoverflow.com/questions/4023830/how-compare-two-strings-in-dot-separated-version-format-in-bash

# Map parameters to coder-friendly names.
Program="$1"
Version="$2"

# Program name must be a valid command.
command -v $Program >/dev/null 2>&1 || { echo "Command: $Program not found. Check spelling."; exit 99; }

# Passed version number must be valid format.
if ! [[ $Version =~ ^([0-9]+\.?)+$ ]]; then
    echo "Version number: $Version has invalid format. Aborting.";
    exit 99
fi

InstalledVersion=$( "$Program" --version | perl -pe '($_)=/([0-9]+([.][0-9]+)+)/' )
# echo "Installed Version: $InstalledVersion"

if [[ $InstalledVersion =~ ^([0-9]+\.?)+$ ]]; then
    l=(${InstalledVersion//./ })
    r=(${Version//./ })
    s=${#l[@]}
    [[ ${#r[@]} -gt ${#l[@]} ]] && s=${#r[@]}

    for i in $(seq 0 $((s - 1))); do
        # echo "Installed ${l[$i]} -gt Test ${r[$i]}?"
        [[ ${l[$i]} -gt ${r[$i]} ]] && exit 0 # Installed version > test version.
        [[ ${l[$i]} -lt ${r[$i]} ]] && exit 1 # Installed version < test version.
    done

    exit 0 # Installed version = test version.
else
    echo "Invalid version number found for command: $Program"
    exit 99
fi

echo "testver - Unreachable code has been reached!"
exit 255
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.