1. $BASH_VERSION을 사용하세요.

1. $BASH_VERSION을 사용하세요.

Bash 버전 번호가 특정 번호보다 큰지 테스트해야 합니다. 예를 들어 다음과 같습니다.

$ 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.

연관 배열을 사용하려면 bash 버전 번호가 4보다 커야 합니다.

내 Bash 스크립트에서는 가능한 한 가장 우아하고 효율적이며 읽기 쉬운 방식으로 한 줄짜리 테스트를 실행하고 싶지만 다른 접근 방식도 허용됩니다.

답변1

노력하다:

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

BASH_VERSINFO이 bash 인스턴스에 대한 버전 정보를 보유하는 멤버가 있는 읽기 전용 배열 변수입니다. bash 2.0에서 도입되었으므로 앞으로 접하게 될 모든 bash 버전에서 지원될 가능성이 높습니다. 그러나 조심하기 위해 0이 변수가 설정되지 않은 이전 버전 bash에 대한 기본값을 포함합니다 .

다른 프로그램에서 버전 정보 추출

LibreOffice, Python, 커널 등에 대해 문의하셨습니다.

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

답변2

버전 번호를 비교하는 대신 기능 자체를 직접 테스트할 수 있습니다. 인식하지 못하면 (적어도 Bash 3.2에서는) declare -A반환 하므로 이에 대해 테스트하십시오(오류도 인쇄함).2-A

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

( 비연관 배열인 declare -A var경우에도 실패하므로 먼저 배열합니다.)varunset

누구도 Bash의 기능을 백포트할 것이라고는 생각하지 않지만 일반적으로 버전보다는 기능을 확인하는 것이 더 적절합니다. Bash의 경우에도 누군가 제한된 기능만 있는 버전을 컴파일할 수 있습니다.


버전 번호를 테스트하는 보다 일반적인 경우는 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

답변3

달성하려는 목표에 접근하는 방법에는 몇 가지가 있습니다.

1. $BASH_VERSION을 사용하세요.

$BASH_VERSION변수 에 무엇이 있는지 보는 것만으로도 충분합니다 . 개인적으로 나는 다음과 같이 서브 쉘을 사용합니다.

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

here-doc의 구문 은 Ubuntu의 Dash이고 다른 시스템의 다른 것일 수 있는 와 <<<함께 사용하려는 경우 이식 가능하지 않습니다./bin/sh

다른 방법은 Case 문이나 if 문을 이용하는 것입니다. 개인적으로 나는 이렇게 할 것이다:

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

시스템에 없거나 설치되어 있는 경우(예: RHEL 또는 FreeBSD) 아무런 소용이 없기 dpkg때문에 이것은 이식성이 없습니다.apt

3. 오류가 있는 경우 set -e를 사용하여 스크립트를 종료합니다.

이 문제를 해결하는 한 가지 방법은 단순히 연관 배열을 사용하고 bash사용할 수 없을 때 종료하는 것입니다. set -e아래 줄을 사용하면 #!/bin/bash스크립트가 연관 배열을 사용할 수 없는 경우 스크립트를 종료할 수 있습니다.

이를 위해서는 사용자에게 "이봐, 정말 bash 버전 4.3 이상이 필요합니다. 그렇지 않으면 스크립트가 작동하지 않습니다."라고 명시적으로 알려야 합니다. 그러면 책임은 사용자에게 있습니다. 그러나 어떤 사람들은 이것이 실제로 소프트웨어 개발에 대한 좋은 접근 방식이 아니라고 주장할 수도 있습니다.

4. 모든 희망을 버리고 이식 가능한 POSIX 호환 스크립트를 작성하세요.

bash스크립트는 Bourne 쉘과 호환되지 않기 때문에 이식성이 없습니다. 작성 중인 스크립트가 Ubuntu뿐만 아니라 다양한 시스템에서 사용될 예정이라면 모든 희망을 버리고 연관 배열이 아닌 다른 것을 사용할 방법을 찾으십시오. 여기에는 두 개의 배열을 사용하거나 구성 파일을 구문 분석하는 것이 포함될 수 있습니다. 구문이 최소한 bash.

답변4

한 줄은 불가능하지만 bash 스크립트는 가능합니다

저는 Stack Overflow의 답변을 활용하는 스크립트를 개발했습니다. 이러한 답변 중 하나는 Dell 직원이 2004년에 DKMS 애플리케이션에 대한 버전 번호 비교를 작성하는 계기가 되었습니다.

코드

아래 bash 스크립트는 명령을 사용하여 실행 가능으로 표시되어야 합니다 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

관련 정보