이와 같은 목록을 정렬하는 가장 간단한 방법은 무엇입니까

이와 같은 목록을 정렬하는 가장 간단한 방법은 무엇입니까

특정 노드에서 어떤 DB2 버전이 최신 버전인지 확인하려고 합니다. /opt/IBM/db2 디렉토리에 DB2 소프트웨어를 설치했습니다. 내가 얻는 디렉토리를 나열하면

V10.5
V9.1
V9.5
V9.5fp10
V9.7
V9.7fp3
V9.7fp6
V9.7fp7

분명히 10.5가 현재 최신 버전이지만 첫 번째 항목이 항상 최신 버전은 아닙니다(예: V11.0을 설치할 때). ksh93에서 최신 항목을 확인하는 상대적으로 쉬운 방법이 있습니까? 각 항목을 주요/부/수정 패키지로 구문 분석할 수 있지만 이는 노동 집약적인 것 같습니다.

답변1

GNU 도구가 있으면 다음을 사용할 수 있습니다.ls -v

또는 Perl을 사용하십시오.

printf "%s\n" * | perl -e '
    @sorted = map {$_->[1]}
              sort {$a->[0] <=> $b->[0] or $a->[1] cmp $b->[1]}
              map {/(\d+\.\d*)/ and [$1, $_]}
              <>;
    print $sorted[-1];
'

답변2

GNU 도구는 없고 노동 집약적인 쉘 스크립트만 사용됩니다.

recentdb2 () (
  cd /opt/IBM/db2 || return 1
  highest=
  himajor=
  himinor=
  hifp=

  for dir in V*.*
  do
        [ ! -d "$dir" ] && continue
        nov="${dir#V*}"
        major="${nov%%.*}"
        notmajor="${nov##*.}"
        minor="${notmajor%%fp*}"
        if [ "$minor" = "$notmajor" ]
        then
                # no FP
                fp=0
        else
                fp="${notmajor##*fp}"
        fi

        # if highest major isn't set, set it and continue
        # else compare major; if higher, set it and continue
        # else compare minor; if higher, set it and continue
        # else compare fp; if higher, set it

        if [ "${himajor:-notset}" = "notset" ]
        then
                highest="$dir"
                himajor="$major"
                himinor="$minor"
                hifp="$fp"
                continue
        fi

        if [ "$major" -gt "$himajor" ]
        then
                highest="$dir"
                himajor="$major"
                himinor="$minor"
                hifp="$fp"
                continue
        elif [ "$major" -eq "$himajor" ] && [ "$minor" -gt "$himinor" ]
        then
                highest="$dir"
                himajor="$major"
                himinor="$minor"
                hifp="$fp"
                continue
        elif [ "$major" -eq "$himajor" ] && [ "$minor" -eq "$himinor" ] && [ "$fp" -gt "$hifp" ]
        then
                highest="$dir"
                himajor="$major"
                himinor="$minor"
                hifp="$fp"
        fi
        # else, the current value is less than the highest value, drop it and continue on
  done
  printf "%s" "$highest"
)

이는 /opt/IBM/db2에서 가장 높은 레벨의 DB2 디렉토리를 리턴하는(시도하는) 함수를 정의합니다.

이 함수는 모두 서브셸에서 실행되므로 다음과 같습니다.

  • 생성된 변수는 완료되면 사라지며,
  • 서브쉘 에서도 cd분리됨

그런 다음 함수는 glob 패턴과 일치하는 /opt/IBM/db2 디렉토리의 항목을 반복합니다. V*.*예를 들어 V11점이 없는 버전이 있는 경우 이를 조정합니다. 첫 번째 테스트는 노숙자들에게 속지 않는지 확인하는 것입니다.문서이 패턴을 맞춰보세요.

V작업이 시작됩니다. 선행 ("no V") 을 제거 하고 다음을 계산합니다.

  • 주요 숫자는 첫 번째 기간 이전의 모든 것입니다.
  • "기본이 아닌 숫자"는 첫 번째 마침표 이후의 모든 것입니다.
  • 마이너 번호는 "비메이저 번호"의 일부입니다.fp
  • 이름에 하나가 있으면 fp(전체 "비주요 번호" 문자열에서 부 번호로 변경되지 않음) fp를 해당 이름으로 설정하고, 그렇지 않으면 0으로 설정합니다.

의견에서 알 수 있듯이 "높음" 변수를 적절하게 테스트하고 설정했습니다. 우리가 만나는 첫 번째 디렉토리는 첫 번째 조건으로 이동합니다. 기본적으로 가장 높은 수준입니다.

그런 다음 후속 디렉토리 항목은 현재 가장 높은 주, 부 및 fp 버전과 비교됩니다.

루프가 완료된 후 함수는 최신 디렉터리 이름을 인쇄합니다.

스크립트를 생성하거나 코드로 가져온 후 함수를 호출하여 함수를 사용합니다.

h=$(recentdb2)

답변3

그리고 zsh:

list=(/opt/IBM/db2/V*(Nn:t))

nglob 한정자가 활성화된 위치숫자$list[1]정렬은 가장 오래된 것( )에서 최신( $list[-1]) 순으로 요청한 대로 정확하게 수행됩니다 .

을 사용하면 내장 기능으로 구축 ksh93된 경우 사용할 수 있습니다.lsast-open버전유형:

(cd /opt/IBM/db2 && command /opt/ast/bin/ls -d -y version V*)

command /opt/ast/bin/ls파일 시스템에 존재하는지 여부 에 관계없이 이 /opt/ast/bin/ls명령이나 해당 내장 명령이 있는 경우 해당 명령을 호출하십시오./opt/ast/bin/ls

다음과 같이 할 수도 있습니다.

PATH=/opt/ast/bin:$PATH
ls -d -y version V*

ls이 내장 기능이 시스템의 /bin또는 것 보다 우선하도록 하려면 /usr/bin.

그렇지 않으면 다음과 같이 할 수 있습니다.

tmp=(/opt/IBM/db2/~(N)V*) # ~(N) equivalent of zsh's N
tmp=("${tmp[@]##*/}")     # equivalent of :t
typeset -A map

# build an associative array where the key is the element with
# all the numbers in them 0-padded to 20 digits. Append a counter
# to make sure all keys are unique.
typeset -Z 20 n=0
for i in "${tmp[@]}"; do
  k=${i//+([0-9])/00000000000000000000\1}
  k=${k//+(0){20}([0-9])/\2}
  map[$k-$n]=$i
  ((n++))
done

# sort the keys of the associative array into $@:
set -s -- "${!map[@]}"

# fill $list with the values for those (now sorted) keys.
typeset -a list
for i do
  list+=("${map[$i]}")
done
printf -- '- %s\n' "${list[@]}"
((${#list[@]})) && printf 'Newest: %s\n' "${list[@]: -1}"

샘플에서 다음을 제공합니다.

- V9.1
- V9.5
- V9.5fp10
- V9.7
- V9.7fp3
- V9.7fp6
- V9.7fp7
- V10.5
Newest: V10.5

관련 정보