What happens for example is if output[2] and [4] are empty, output[6] will shift up to the line corresponding to output [2].
В этом случае у вас действительно нет пустых значений вместо 2 и 4, просто у вас меньше значений, чем вы ожидаете.
Рассмотрим назначения массивов:
array1=(a b c d) array2=(A D)
Первый устанавливает
array1[0]
вa
,array1[1]
вb
и т. д. Второй устанавливаетarray2[0]
вA
иarray2[1]
вD
. Невозможно узнать, должны ли быть пустые значения междуA
иD
. Они должны быть явно указаны в задании :.
array2=(A "" "" D)
Возможно, вы заполняете массив
output
каким-то другим способом, но поскольку вы не показываете, как это делается, нет возможности прокомментировать это. Вероятно, у вас есть случай, аналогичный приведенному выше :: «пустые» значения вообще не рассматриваются как значения тем, что заполняет массивoutput
.Если вы присваиваете значение массиву из расширения и полагаетесь на разбиение слов -, вы не можете избежать этого. (Даже если
IFS
содержит только новую строку, он будет складывать последовательные пустые строки новой строки в одну, удаляя пустые строки ). Если вы используетеmapfile
, то пустые строки должны отображаться как элементы массива по умолчанию.В любом случае ваш цикл для обнуления пустых элементов массива не работает, потому что вы вообще не присваиваете значение массиву внутри цикла (), и даже если вы это сделали, тело цикла выполняется в подоболочка (, отмеченная скобками
(...)
), так что никакие присваивания в любом случае не будут выполняться вне тела цикла.Вы не можете использовать
for x in "${output[@]}"
для полезного изменения элементов массива, так какx
получает только копию значений массива, его изменение не изменяет оригиналы. Вам нужно будет перебрать индексы массива, чтобы иметь возможность указывать на массив:somearray=(1 "" "" 4) for i in "${!somearray[@]}"; do if [[ -z "${somearray[$i]}" ]]; then somearray[$i]=0; fi; done echo "${somearray[@]}"
печатает
1 0 0 4
.В добавленном примере кода присваивание
output+=( $(ssh $h du -sh $path) )
не добавит пустых элементов. Отсутствующие пути будут просто исключены из массива. Учтите, что сначалаdu $path
ничего не печатает, если путь не существует. (Помимо ошибки,но это идет в stderr и не фиксируется подстановкой команд. )Кроме того, даже если была напечатана пустая строка (или пробелы/табуляции ), разделение слов удаляет последовательные пробелы.Попробуйте, например.
array=( $( printf "foo\n\nbar\n" ) )
, он создает массив из двух элементов.Кроме того, круглые скобки в цикле замены запускают подоболочку, поэтому любые модификации массива вступят в силу только внутри этой подоболочки. В общем, вы не хотите группировать команды оболочки в круглых скобках, если только вы точно не знаете, что вам нужна подоболочка.
Вы можете заключить подстановку команды(
"$(ssh... du)"
)в кавычки, чтобы убедиться, что вы получаете только одну строку, но вы, вероятно, захотите отделить размер от имени пути.Попробуйте сделать что-то подобное, чтобы собрать пути и их размеры в один массив:
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
Теперь каждый четный элемент массива содержит размер, а каждый нечетный — соответствующее имя хоста и путь, что немного похоже на результат разделения вывода
du
. Два расширения параметровoutput
иsize
удалите все после табуляции, а затем замените размер на ноль, если он пуст.В качестве альтернативы можно построить ассоциативный массив , индексированный по хосту+пути:
declare -A array ... array["$host:$path"]=$size