Respostas:
No Bash 4, você pode usar matrizes associativas:
# set up array of constants
declare -A array
for constant in foo bar baz
do
array[$constant]=1
done
# test for existence
test1="bar"
test2="xyzzy"
if [[ ${array[$test1]} ]]; then echo "Exists"; fi # Exists
if [[ ${array[$test2]} ]]; then echo "Exists"; fi # doesn't
Para configurar a matriz inicialmente, você também pode fazer atribuições diretas:
array[foo]=1
array[bar]=1
# etc.
ou desta maneira:
array=([foo]=1 [bar]=1 [baz]=1)
${array[$test1]}
é simples, mas tem um problema: não funcionará se você usar set -u
seus scripts (o que é recomendado), pois você obteria "variável não acoplada".
É uma questão antiga, mas eu acho que é a solução mais simples ainda não apareceu: test ${array[key]+_}
. Exemplo:
declare -A xs=([a]=1 [b]="")
test ${xs[a]+_} && echo "a is set"
test ${xs[b]+_} && echo "b is set"
test ${xs[c]+_} && echo "c is set"
Saídas:
a is set
b is set
Para ver como isso funciona, verifique isso .
env
para evitar ambiguidades em aliases, progs e outras funções que possam ter adotado o nome "teste". Como acima env test ${xs[a]+_} && echo "a is set"
. Você também pode obter essa funcionalidade usando colchetes duplos, o mesmo truque e depois verificando se [[ ! -z "${xs[b]+_}" ]] && echo "b is set"
[[ ${xs[b]+set} ]]
Existe uma maneira de testar se um elemento de uma matriz associativa existe (não definido), isso é diferente de vazio:
isNotSet() {
if [[ ! ${!1} && ${!1-_} ]]
then
return 1
fi
}
Então use-o:
declare -A assoc
KEY="key"
isNotSet assoc[${KEY}]
if [ $? -ne 0 ]
then
echo "${KEY} is not set."
fi
if ! some_check then return 1
= some_check
. Assim: isNotSet() { [[ ... ]] }
. Confira minha solução abaixo, você pode fazer isso em uma verificação simples.
Você pode ver se uma entrada está presente canalizando o conteúdo da matriz para grep.
printf "%s\n" "${mydata[@]}" | grep "^${val}$"
Você também pode obter o índice de uma entrada com grep -n, que retorna o número da linha de uma correspondência (lembre-se de subtrair 1 para obter o índice baseado em zero). Isso será razoavelmente rápido, exceto para matrizes muito grandes.
# given the following data
mydata=(a b c "hello world")
for val in a c hello "hello world"
do
# get line # of 1st matching entry
ix=$( printf "%s\n" "${mydata[@]}" | grep -n -m 1 "^${val}$" | cut -d ":" -f1 )
if [[ -z $ix ]]
then
echo $val missing
else
# subtract 1. Bash arrays are zero-based, but grep -n returns 1 for 1st line, not 0
echo $val found at $(( ix-1 ))
fi
done
a found at 0
c found at 2
hello missing
hello world found at 3
explicação:
$( ... )
é o mesmo que usar backticks para capturar a saída de um comando em uma variável printf
gera mydata um elemento por linha @
de *.
evitar isso, dividem o "olá mundo" em duas linhas)grep
pesquisa a string exata: ^
e $
corresponde ao início e ao fim da linhagrep -n
retorna a linha #, na forma de 4: hello world grep -m 1
encontra apenas a primeira correspondênciacut
extrai apenas o número da linha Obviamente, você pode dobrar a subtração no comando. Mas, em seguida, teste -1 em falta:
ix=$(( $( printf "%s\n" "${mydata[@]}" | grep -n -m 1 "^${val}$" | cut -d ":" -f1 ) - 1 ))
if [[ $ix == -1 ]]; then echo missing; else ... fi
$(( ... ))
faz aritmética inteiraEu não acho que você pode fazê-lo corretamente sem fazer loop, a menos que tenha dados muito limitados na matriz.
Aqui está uma variante simples, isso diria corretamente que "Super User"
existe na matriz. Mas também diria que "uper Use"
está na matriz.
MyArray=('Super User' 'Stack Overflow' 'Server Fault' 'Jeff' );
FINDME="Super User"
FOUND=`echo ${MyArray[*]} | grep "$FINDME"`
if [ "${FOUND}" != "" ]; then
echo Array contains: $FINDME
else
echo $FINDME not found
fi
#
# If you where to add anchors < and > to the data it could work
# This would find "Super User" but not "uper Use"
#
MyArray2=('<Super User>' '<Stack Overflow>' '<Server Fault>' '<Jeff>' );
FOUND=`echo ${MyArray2[*]} | grep "<$FINDME>"`
if [ "${FOUND}" != "" ]; then
echo Array contains: $FINDME
else
echo $FINDME not found
fi
O problema é que não há uma maneira fácil de adicionar as âncoras (que eu possa pensar) além de percorrer o array. A menos que você possa adicioná-los antes de colocá-los na matriz ...
grep "\b$FINDME\b"
). Provavelmente poderia trabalhar com constantes não alfanuméricos que não têm espaços, com "(^| )$FINDME(\$| )"
(ou algo assim ... Eu nunca fui capaz de aprender o sabor de usos regexp grep.)
#!/bin/bash
function in_array {
ARRAY=$2
for e in ${ARRAY[*]}
do
if [[ "$e" == "$1" ]]
then
return 0
fi
done
return 1
}
my_array=(Drupal Wordpress Joomla)
if in_array "Drupal" "${my_array[*]}"
then
echo "Found"
else
echo "Not found"
fi
in_array
. Cheers
${ARRAY[@]}
deve ser usado.