Цикл через массив массивов строки с пробелами
Я пытаюсь перебрать массив, содержащий другие массивы, и эти массивы состоят из строк с пробелами. Проблема в том, что я не могу сохранить промежуток в строке. Строка с пробелами делится на несколько элементов, если я изменяю IFS на \n, или все элементы массива рассматриваются как 1 элемент, если я оставлю IFS без изменений здесь пример кода:
#!/bin/sh
low1=("AA QQ" "BB LL")
low2=("CC" "DD")
low3=("EE" "FF")
high=(low1 low2 low3)
for high_item in ${high[@]}
do
eval arrayz=\${$high_item[@]}
#IFS=$'\n'
for item in $arrayz
do
echo $item
done
done
Вывод:
AA
QQ
BB
LL
CC
DD
EE
FF
Как вы видите, элементы "AA QQ" и "BB LL" были разделены.
Если я раскомментирую строку, которая устанавливает IFS
в \n
, я получаю следующее:
AA QQ BB LL
CC DD
EE FF
Теперь "AA QQ" и "BB LL" объединены!
В любом случае я могу сохранить эти элементы так же, как они оригинальны... Мне нужен вывод, чтобы выглядеть так:
AA QQ
BB LL
CC
DD
EE
FF
Ответы
Ответ 1
Я думаю, вы имели в виду, что вывод должен выглядеть так:
AA QQ
BB LL
CC
DD
EE
FF
то есть:.
${low1[0]}
${low1[1]}
${low2[0]}
${low2[1]}
${low3[0]}
${low3[1]}
Это может быть выполнено с помощью:
#!/bin/bash
low1=("AA QQ" "BB LL")
low2=("CC" "DD")
low3=("EE" "FF")
high=(low1 low2 low3)
for high_item in ${high[@]}
do
x="${high_item}[@]" # -> "low1[@]"
arrays=( "${!x}" )
#IFS=$'\n'
for item in "${arrays[@]}"
do
echo "$item"
done
done
И пожалуйста всегда используйте #!/bin/bash
для bash скриптов.
Объяснение: ${!x}
- косвенное изменение переменной. Он вычисляет значение переменной с именем, содержащимся в $x
.
Для наших нужд x
должен иметь суффикс [@]
для расширения массива. Особенно отметим, что это x=${high_item}[@]
и не x=${high_item[@]}
.
И вы должны оценить его в контексте массива; в противном случае он не будет работать так, как ожидалось (если вы делаете arrays=${!x}
).
Ah, и как окончательное замечание: IFS
здесь не имеет никакого значения. Пока вы работаете над цитируемыми массивами, IFS
не вступает в игру.
Ответ 2
Замените eval
косвенным расширением параметра, и вы получите то, что, как я думаю, вы хотите (хотя оно не соответствует вашему текущему выходу:
for high_item in "${high[@]}"
do
arrayz="$high_item[@]"
# arrayz is just a string like "low1[@]"
for item in "${!arrayz}"
do
echo $item
done
done
Обратите внимание на необходимость цитировать расширение массива во внутреннем цикле, чтобы сохранить пробелы в элементах low1
.