bash에서 배열 요소가 모두 같은지 테스트하는 방법은 무엇입니까?


15

다음 배열은 각 Linux 시스템의 디스크 수를 나타냅니다.

단일 어레이 에는 Linux 시스템 의 디스크 수가 포함됩니다 .

echo ${ARRAY_DISK_Quantity[*]}
4 4 4 4 2 4 4 4

모든 배열의 값이 동일한지를 식별하는 간단한 방법은 무엇입니까?

양호한 상태 :

4 4 4 4 4 4 4 4

나쁜 상태 :

4 4 4 4 4 4 2 4

나쁜 상태 :

6 6 6 6 6 6 6 6 6 6 2 6 2

너무 많은 답변과 투표가 없습니까?
Jesse_b

이것은 정수만 테스트합니까 아니면 문자열도 테스트해야합니까?
Jesse_b

난 그냥 최고의 답변을 기다리고 곧 투표 투표 곧 걱정
yael

나는 다른 사람들을 의미했다. 이 질문은 공감대 IMO가 필요합니다.
Jesse_b

최소한이 수준의 복잡성이 필요하다면, 너무 늦을 때까지 실제 프로그래밍 언어를 사용하는 것이 좋습니다.
Display Name

답변:


11

bash+ GNU sort+ GNU grep솔루션 :

if [ "${#array[@]}" -gt 0 ] && [ $(printf "%s\000" "${array[@]}" | 
       LC_ALL=C sort -z -u |
       grep -z -c .) -eq 1 ] ; then
  echo ok
else
  echo bad
fi

영어 설명 : 배열의 요소를 고유하게 정렬하면 하나의 요소 만 있으면 "ok"를 인쇄하십시오. 그렇지 않으면 "나쁜"을 인쇄하십시오.

어레이가 NUL 각 소자 분리 바이트 인쇄 (온 의존 정렬로 GNU 파이프 -z일명 --zero-terminated-u일명 --unique옵션) 다음에 grep(옵션을 사용하여 -z일명 --null-data-c일명 --count출력 라인을 계산).

이전 버전과 달리 wc줄 바꿈으로 끝나는 입력 줄이 필요하기 때문에 여기에서 사용할 수 없으며 NUL 구분 기호 사용의 목적 을 상실한 후 NUL을 줄 바꿈으로 사용 sed하거나 tr변환해야 sort합니다. grep -c합리적인 대체물을 만듭니다.


다음은 함수로 다시 작성된 것과 같습니다.

function count_unique() {
  local LC_ALL=C

  if [ "$#" -eq 0 ] ; then 
    echo 0
  else
    echo "$(printf "%s\000" "$@" |
              sort --zero-terminated --unique |
              grep --null-data --count .)"
  fi
}



ARRAY_DISK_Quantity=(4 4 4 4 2 4 4 4)

if [ "$(count_unique "${ARRAY_DISK_Quantity[@]}")" -eq 1 ] ; then
  echo "ok"
else
  echo "bad"
fi

1
참고 sort -u고유 한 요소이지만 종류의 요소의 각 세트 같은 중 하나를 반환하지 않습니다. 예를 들어, ARRAY_DISK_Quantity=(① ②)로케일이 일반적으로 두 문자의 정렬을 결정하는 GNU 시스템에서는 "ok"라고 표시됩니다 . LC_ALL=C sort -u바이트 단위 고유성을 원할 것 입니다.
Stéphane Chazelas

CLI에서 추가 디스크가 나타나지 않으면이 구문을 추가해야하는 경우에도 실패합니다
yael

[[`printf "% s \ n" "$ {ARRAY_DISK_Quantity [@]}" "| wc -l`-eq`printf "% s \ n" "$ {ARRAY_DISK_Quantity [@]}"| grep -c "0"`]] && echo
failure

@ StéphaneChazelas는 IFS 문제와 마찬가지로 로케일 문제를 처리 할 가치가 있습니다. 빈 목록에 대한 테스트는 IMO이며 별도로 수행하는 것이 가장 좋습니다. 빈 세트에서 고유하지 않은 요소를 확인할 필요가 없습니다.
cas

안녕하세요 Cas 나는 당신의 이전 답변을 선호합니다
yael

8

zsh:

if ((${#${(u)ARRAY_DISK_Quantity[@]}} == 1)); then
  echo OK
else
  echo not OK
fi

고유(u)을 확장하기위한 매개 변수 확장 플래그는 어디에 있습니까 ? 따라서 배열에서 고유 한 값의 수를 얻습니다.

교체 == 1<= 1당신은 빈 배열 확인을 고려해야 할 것입니다.

을 사용 ksh93하면 배열을 정렬하고 첫 번째 요소가 마지막 요소와 같은지 확인할 수 있습니다.

set -s -- "${ARRAY_DISK_Quantity[@]}"
if [ "$1" = "${@: -1}" ]; then
  echo OK
else
  echo not OK
fi

ksh88 또는 pdksh / mksh를 사용하는 경우 :

set -s -- "${ARRAY_DISK_Quantity[@]}"
if eval '[ "$1" = "${'"$#"'}" ]'; then
  echo OK
else
  echo not OK
fi

를 사용하면 bash아마도 루프가 필요할 것입니다.

unique_values() {
  typeset i
  for i do
    [ "$1" = "$i" ] || return 1
  done
  return 0
}
if unique_values "${ARRAY_DISK_Quantity[@]}"; then
  echo OK
else
  echo not OK
fi

배열 지원 (ksh, zsh, bash, yash)이있는 모든 Bourne과 같은 셸에서 작동합니다.

빈 배열에 대해서는 OK를 반환합니다. [ "$#" -gt 0 ] || return원하지 않는 경우 함수 시작 부분에 a 를 추가하십시오 .


이 모든 대답은 bash를 지원하지 않는 것 같습니다.
yael

@ yael, bash 솔루션 편집을 참조하십시오. 하지만 왜 사용 bash하시겠습니까?
Stéphane Chazelas

배쉬에 대한 도움말 페이지를 typeset말한다는 Obsolete. See `help declare'.당신이 대신 그것을 사용하는 이유가 있습니까 local또는 declare?
wjandrea

1
@wjandrea typeset는 모든 4 개의 쉘에서 작동하는 것입니다. 또한의 원래 (bash는 대부분이 변수 범위 지정 유형 설정 및 선언에 올 때 ksh88을 복사하지만, 이름을 변경하기로 결정했다 80 년대 초반에 KSH에서 하나 typeset declare와 만들기 typeset선언에 별명을).
Stéphane Chazelas

4

bash+ 해결 awk:

function get_status() {
    arr=("$@")    # get the array passed as argument
    if awk 'v && $1!=v{ exit 1 }{ v=$1 }' <(printf "%d\n" "${arr[@]}"); then 
        echo "status: Ok"
    else 
        echo "status: Bad"
    fi
}

테스트 사례 # 1 :

ARRAY_DISK_Quantity=(4 4 4 4 4 2 4 4)
get_status "${ARRAY_DISK_Quantity[@]}"
status: Bad

테스트 사례 # 2 :

ARRAY_DISK_Quantity=(4 4 4 4 4 4 4 4)
get_status "${ARRAY_DISK_Quantity[@]}"
status: Ok

4

문자열과 함께 작동 해야하는 또 다른 bash 전용 솔루션이 있습니다.

isarray.equal () {
    local placeholder="$1"
    local num=0
    while (( $# )); do
        if [[ "$1" != "$placeholder" ]]; then
            num=1
            echo 'Bad' && break
        fi
        shift
    done
    [[ "$num" -ne 1 ]] && echo 'Okay'
}

데모:

[root@JBSTEST001 ~]# ARRAY_DISK_Quantity=(4 4 4 4 2 4 4 4)
[root@JBSTEST001 ~]# isarray.equal "${ARRAY_DISK_Quantity[@]}"
Bad
[root@JBSTEST001 ~]# ARRAY_DISK_Quantity=(4 4 4 4 4 4 4 4)
[root@JBSTEST001 ~]# isarray.equal "${ARRAY_DISK_Quantity[@]}"
Okay
[root@JBSTEST001 ~]# ARRAY_DISK_Quantity=(four four four four two four four four)
[root@JBSTEST001 ~]# isarray.equal "${ARRAY_DISK_Quantity[@]}"
Bad
[root@JBSTEST001 ~]# ARRAY_DISK_Quantity=(four four four four four four four four)
[root@JBSTEST001 ~]# isarray.equal "${ARRAY_DISK_Quantity[@]}"
Okay

Bash는 꽤 허용 적이지만 함수 이름에는 점이 유효하지 않습니다. 함수 내보내기와 같은 문제가 발생할 수 있습니다.
wjandrea


2

bash와 GNU grep으로 :

if grep -qE '^([0-9]+)( \1)*$' <<< "${ARRAY_DISK_Quantity[@]}"; then 
  echo "okay"
else
  echo "not okay"
fi

예,하지만 (10 10 10 10)은 어떻습니까? 그렇지 않으면 아주 좋습니다.
Joe

@ 조 : 잘 잡아. 내 답변을 업데이트했습니다.
Cyrus

1

POSIX Awk는 다음과 같습니다.

awk 'BEGIN {while (++z < ARGC) if (ARGV[z] != ARGV[1]) exit 1}' "${ARRAY_DISK_Quantity[@]}"

0

떠들썩한 파티 만 용액 (가정 a된다 ARRAY_DISK_Quantity)

ttt=${a[0]}
res=0
for i in "${a[@]}"
do 
    let res+=$(if [ "$ttt" -ne "$i" ]; then echo 1; else echo 0; fi);  
done
if [ "$res" -eq 0 ]
then 
    echo "ok"
else
    echo "bad"
fi

작동하지만 하나만 있으면 모든 오류를 계산합니다.if [ "$ttt" -ne "$i" ]; then res=1; break; fi;
Joe

0

for 루프를 사용하여 각 배열 요소를 다음 배열과 비교하십시오. 마지막 요소를 마지막에 아무것도 비교하지 않도록 배열의 길이보다 작은 루프 반복을 종료하십시오.

for (( i=0; i<((${#array[@]}-1)); i++ )); do
    [ "${array[$i]}" != "${array[(($i+1))]}" ] && echo "Mismatch"
done
echo "Match"

U & L에 오신 것을 환영합니다. 이 코드는 불일치가 발견 되더라도 "일치"를 인쇄합니다. 의도 된 것입니까?
fra-san
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.