What happens for example is if output[2] and [4] are empty, output[6] will shift up to the line corresponding to output [2].
Nesse caso, você não tem valores vazios no lugar de 2 e 4, é apenas que você tem menos valores do que o esperado.
Considere as atribuições da matriz:
array1=(a b c d)
array2=(A D)
O primeiro define array1[0]
a a
, array1[1]
a b
etc. O segundo define array2[0]
a A
e array2[1]
a D
. Não há como saber se deveria haver valores vazios entre A
e D
. Eles precisariam estar na tarefa explicitamente:
array2=(A "" "" D)
Você provavelmente está preenchendo o array output
de alguma outra forma, mas como você não mostra como é feito, não há como comentá-lo. Você provavelmente tem um caso semelhante ao acima: os valores "vazios" não são vistos como valores por qualquer que seja o preenchimento da matriz output
.
Se você está atribuindo a matriz a partir de uma expansão e confiando na divisão de palavras, não é possível evitar isso. (Mesmo se IFS
contiver apenas nova linha, ele irá dobrar novas linhas vazias consecutivas para uma, removendo linhas vazias). Se você estiver usando mapfile
, as linhas vazias devem aparecer como elementos da matriz por padrão.
Em qualquer caso, seu loop para zero elementos de array vazios não funciona porque você não atribui ao array dentro do loop (de jeito nenhum), e mesmo se você o fez, o corpo do loop é executado em um subshell (como marcado pelo parêntese (...)
), portanto, quaisquer atribuições não ocorreriam fora do corpo do loop, de qualquer forma.
Você não pode realmente usar um for x in "${output[@]}"
para modificar os elementos da matriz, já que x
obtém apenas uma cópia dos valores da matriz, modificando-a não altera os originais. Você precisaria percorrer os índices da matriz para poder apontar para a matriz:
somearray=(1 "" "" 4)
for i in "${!somearray[@]}"; do
if [[ -z "${somearray[$i]}" ]]; then
somearray[$i]=0;
fi;
done
echo "${somearray[@]}"
imprime 1 0 0 4
.
Em seu código de amostra adicionado, a atribuição output+=( $(ssh $h du -sh $path) )
não adicionará nenhum elemento vazio. Os caminhos ausentes serão apenas omitidos da matriz. Considere que primeiro, du $path
não imprime nada se o caminho não existir. (Além de um erro, mas que vai para stderr, e não é capturado pela substituição de comando.) Além disso, mesmo que tenha sido impressa uma linha vazia (ou espaços / tabulações), a divisão de palavras remove espaços em branco consecutivos.
Experimente, por exemplo array=( $( printf "foo\n\nbar\n" ) )
, cria uma matriz de dois elementos.
Além disso, os parênteses no loop de substituição iniciam um subshell, portanto, quaisquer modificações no array só entrarão em vigor dentro desse subshell. Em geral, você não quer agrupar comandos shell com parênteses, a menos que você saiba que você quer uma subshell em particular.
Você pode colocar aspas ao redor da substituição do comando ( "$(ssh ... du)"
) para ter certeza de obter exatamente uma string, mas provavelmente você quer separar o tamanho do nome do caminho.
Tente algo assim para coletar os caminhos e seus tamanhos em uma única matriz:
for host in "${hosts[@]}"; do
for path in "${paths[@]}"; do
output="$(ssh "$host" du -sh "$path")"
size="${output%%$'\t'*}" # needs Bash/ksh/zsh
size="${size:-0}"
sizes+=( "$size" "$host:$path" )
done
done
Agora, todo elemento de matriz uniforme contém um tamanho e todo ímpar, o nome de host e o caminho correspondentes, um pouco parecido com o que resultaria na divisão da saída de du
. As expansões de dois parâmetros de output
e size
remova tudo após uma tabulação e substitua o tamanho por zero, se estiver vazio.
Como alternativa, você pode criar uma matriz associativa , indexada pelo host + caminho:
declare -A array
...
array["$host:$path"]=$size