How to test if array elements are all equal in bash?
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
English explanation: if unique-sorting the elements of the array results in only one element, then print "ok". Otherwise print "bad".
The array is printed with NUL bytes separating each element, piped into GNU sort (relying on the -z
aka --zero-terminated
and -u
aka --unique
options), and then into grep
(using options -z
aka --null-data
and -c
aka --count
) to count the output lines.
Unlike my previous version, I can't use wc
here because it requires input lines terminated with a newline...and using sed
or tr
to convert NULs to newlines after the sort
would defeat the purpose of using NUL separators. grep -c
makes a reasonable substitute.
Here's the same thing rewritten as a function:
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
With zsh
:
if ((${#${(u)ARRAY_DISK_Quantity[@]}} == 1)); then
echo OK
else
echo not OK
fi
Where (u)
is a parameter expansion flag to expand unique values. So we're getting a count of the unique values in the array.
Replace == 1
with <= 1
is you want to consider an empty array is OK.
With ksh93
, you could sort the array and check that the first element is the same as the last:
set -s -- "${ARRAY_DISK_Quantity[@]}"
if [ "$1" = "${@: -1}" ]; then
echo OK
else
echo not OK
fi
With ksh88 or pdksh/mksh:
set -s -- "${ARRAY_DISK_Quantity[@]}"
if eval '[ "$1" = "${'"$#"'}" ]'; then
echo OK
else
echo not OK
fi
With bash
, you'd probably need a loop:
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
(would work with all the Bourne-like shells with array support (ksh, zsh, bash, yash)).
Note that it returns OK for an empty array. Add a [ "$#" -gt 0 ] || return
at the start of the function if you don't want that.
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
}
Test case #1:
ARRAY_DISK_Quantity=(4 4 4 4 4 2 4 4)
get_status "${ARRAY_DISK_Quantity[@]}"
status: Bad
Test case #2:
ARRAY_DISK_Quantity=(4 4 4 4 4 4 4 4)
get_status "${ARRAY_DISK_Quantity[@]}"
status: Ok