Existe uma boa maneira de verificar se uma matriz tem um elemento no bash (melhor do que repetir)?
Como alternativa, existe outra maneira de verificar se um número ou sequência é igual a um conjunto de constantes predefinidas?
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ê usarset -u
seus scripts (o que é recomendado), pois você obteria "variável não acoplada".set -u
: davidpashley.com/articles/writing-robust-shell-scripts.html , blog.hashbang0.com/2010/05/18/robust-bash-scripts-part-one , openews.net/2012/bash- script para gravação robusta .É uma questão antiga, mas eu acho que é a solução mais simples ainda não apareceu:
test ${array[key]+_}
. Exemplo:Saídas:
Para ver como isso funciona, verifique isso .
fonte
env
para evitar ambiguidades em aliases, progs e outras funções que possam ter adotado o nome "teste". Como acimaenv 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:
Então use-o:
fonte
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.
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.
explicação:
$( ... )
é o mesmo que usar backticks para capturar a saída de um comando em uma variávelprintf
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 worldgrep -m 1
encontra apenas a primeira correspondênciacut
extrai apenas o número da linhaObviamente, você pode dobrar a subtração no comando. Mas, em seguida, teste -1 em falta:
$(( ... ))
faz aritmética inteirafonte
Eu 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.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 ...
fonte
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.)fonte
in_array
. Cheers${ARRAY[@]}
deve ser usado.