2015-04-08 5 views
1

У меня есть два массива в моей Баш скрипт:Печать массивов в Баш

A=('AB' 'CD' 'EF' 'GH' 'IJ' 'KL' 'MN'); 

B=('1' '2' '3' '4' '5' '6' '7'); 

Я хочу, чтобы иметь возможность объединить массивы в переменную (скажем, в «слиянии»), так что операция, как:

echo $merge 

... напечатает

(AB, 1, CD, 2, EF, 3, GH, 4, IJ, 5, KL, 6, MN, 7) 

длина/размер массивов не должны быть равны. Любые мысли о том, как это сделать?

Спасибо!

ответ

1

Я бы сделал это близко, но немного отличается. Вместо того чтобы найти самый длинный массив, выбирая самый короткий является единственным способом, чтобы обеспечить включение 1-к-1 элементов из каждого массива:

#!/bin/bash 

A=('AB' 'CD' 'EF' 'GH' 'IJ' 'KL' 'MN') 
B=('1' '2' '3' '4' '5' '6' '7' '8') 
len=${#A[@]} 
declare -a combined 

[ $len -lt ${#B[@]} ] || len=${#B[@]} # find shortest array 

for ((i = 0; i < $len; i++)); do 

    [ -n ${A[i]} ] && combined+=("${A[i]}") 
    [ -n ${B[i]} ] && combined+=("${B[i]}") 

done 

merge=$(printf " %s," ${combined[@]}) 
merge=${merge%,} 
merge="($merge)" 

echo $merge 

exit 0 

Выход

$ bash array_merge.sh 
(AB, 1, CD, 2, EF, 3, GH, 4, IJ, 5, KL, 6, MN, 7) 
2
A=('AB' 'CD' 'EF' 'GH' 'IJ' 'KL' 'MN') 
B=('1' '2' '3' '4' '5' '6' '7' '8') 
len=${#A[@]} 
[[ $len -lt ${#B[@]} ]] && len=${#B[@]} 
out="" 
for i in $(seq 0 $((len-1)));do 
    [[ -n "${A[$i]}" ]] && out=$out","${A[$i]} 
    [[ -n "${B[$i]}" ]] && out=$out","${B[$i]} 
done 
echo ${out:1} 

Примечание: Даю B 8 элементов, так что, если длина А и В не то же самое, просто положить остальные элементы длинного списка к хвосту выхода

Объясните:

3 и 4 строки кода, просто найдите максимальную длину двух списков. Затем используйте цикл for, чтобы поместить в список каждого-го списка не пустой элемент в выходной файл. В последнем случае удалите первый разделитель ,.

Надеюсь, это вам поможет.

+0

Избегайте использования '$ (seq 0 $ ((len-1)))'. С-стиль для более подходит: 'for ((i = 0; i <$ len; i ++)); do' –

+0

@ DavidC.Rankin спасибо. – amow

+0

Несомненно, причина, по которой я упоминаю, иногда может понадобиться отрегулировать индекс внутри цикла. Использование 'seq' устраняет эту гибкость. Второй момент заключается в том, что он бесполезно создает другую подоболочку для запуска 'seq', где уже встроенный синтаксис' for' цикла уже предоставляет это для вас. Вы отлично поработали с вашим ответом. –

0
A=('AB' 'CD' 'EF') 
B=('1' '2' '3' '4' '5' '6' '7' '8') 
IFS=$'\n' 
m=($(paste -d\\n <(printf %s,\\n "${A[@]}") \ 
       <(printf %s,\\n "${B[@]}" | head -c-2))) 
merge=\("${m[@]}"\) 
echo "$merge" 

Выходной :

(AB, 1, CD, 2, EF, 3, 4, 5, 6, 7, 8)