web-dev-qa-db-fra.com

Comment tester si les éléments de tableau sont tous égaux à Bash?

Le tableau suivant représentait le nombre de disques sur chaque machines Linux

Chacun tableau unique inclut le nombre de disques sur une machine Linux.

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

quel est le moyen simple d'identifier que toutes les valeurs de la matrice sont égales?

Bon état:

4 4 4 4 4 4 4 4

Mauvais état:

4 4 4 4 4 4 2 4

Mauvais état:

6 6 6 6 6 6 6 6 6 6 2 6 2
15
yael

bash + GNU sort + GNU grep Solution:

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

FRANÇAIS Explication: Si le tri unique des éléments de la matrice ne donne qu'un seul élément, puis imprimez "OK". Sinon, imprimez "mauvais".

La matrice est imprimée avec des octets Nul séparant chaque élément, canalisé dans GNU Trier (s'appuyer sur le -z alias --zero-terminated et -u alias --unique options), puis en grep (en utilisant Options -z alias --null-data et -c alias --count) Pour compter les lignes de sortie.

Contrairement à ma version précédente, je ne peux pas utiliser wc ici car il nécessite des lignes de saisie terminées avec une nouvelle ligne ... et en utilisant sed ou tr pour convertir les nuls aux nouvelles lignes suivantes. Le sort vaincrait le but d'utiliser des séparateurs nul. grep -c fait un substitut raisonnable.


Voici la même chose réécrite comme une fonction:

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
12
cas

Avec zsh:

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

(u) est un drapeau d'expansion des paramètres pour développer nique valeurs. Nous obtenons donc un nombre de valeurs uniques dans le tableau.

Remplacer == 1 avec <= 1 Est-ce que vous voulez envisager un tableau vide est OK.

Avec ksh93, vous pouvez trier le tableau et vérifier que le premier élément est le même que le dernier:

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

Avec ksh88 ou pdksh/mksh:

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

Avec bash, vous auriez probablement besoin d'une boucle:

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

(Travaillerait avec toutes les coquilles de type Bourne avec support réseau (ksh, zsh, bash, yash)).

Notez qu'il renvoie OK pour un tableau vide. Ajouter un [ "$#" -gt 0 ] || return Au début de la fonction si vous ne le souhaitez pas.

8
Stéphane Chazelas

bash + awk Soltion:

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
}

Cas de test n ° 1:

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

Cas de test n ° 2:

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

J'ai une autre solution bash uniquement qui devrait également travailler avec des chaînes:

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'
}

Manifestation:

[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
4
jesse_b

Avec bash et GNU grep:

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

Voici POSIX AWK:

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

bash Seul Solution (en supposant que a est 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
0
Bhavin Chirag

Utilisez une boucle pour comparer chaque élément de tableau à l'autre. Mettre fin à la boucle une itération inférieure à la longueur de la matrice pour éviter de comparer le dernier élément à rien à la fin.

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