Распечатать элементы массива на отдельных строках в Bash?

229

Как напечатать элемент массива массива Bash на отдельных строках? Это работает, но, безусловно, есть лучший способ:

$ my_array=(one two three)
$ for i in ${my_array[@]}; do echo $i; done
one
two
three

Пробовал этот, но это не сработало:

$ IFS=$'\n' echo ${my_array[*]}
one two three
Аксель Брегнсбо
источник

Ответы:

436

Попробуйте сделать это:

$ printf '%s\n' "${my_array[@]}"

Разница между $@и $*:

  • Без кавычек результаты не уточняются. В Bash оба расширяются до отдельных аргументов, а затем разбиваются на слова и разбиваются.

  • В кавычках "$@"раскрывает каждый элемент в качестве отдельного аргумента, а "$*" расширяет до аргументов, объединенных в один аргумент: "$1c$2c..."(где c- первый символ IFS).

Вы почти всегда хотите "$@". То же самое и для "${arr[@]}".

Всегда цитируйте их!

Жиль Квено
источник
5
И обратите внимание, двойные кавычки вокруг ссылки на переменную важны, если вы хотите убедиться, что элементы с внутренними пробелами случайно не разделены.
Danfuzz
4
@sputnick: не работает, элементы массива заканчиваются одной строкой
Аксель Брегнсбо,
1
Каковы два дефиса после команды для? Я не нашел никаких ссылок на это в руководстве.
Joanpau
3
Есть ли способ сделать так, чтобы он не выводил пустых строк, если в массиве нет элементов без необходимости | grep -v '^$'?
Ноэль Яп
2
@espaciomore '% s \ n' - это формат вывода функции printf. % s означает заполнитель для строкового аргумента (в данном случае элемент массива) и \ n добавляет после него разрыв строки. Таким образом, будет строка и разрыв строки на выходе для каждого элемента в массиве.
Кожа
71

Просто приведите аргумент в пользу эха:

( IFS=$'\n'; echo "${my_array[*]}" )

субоболочка помогает восстановить IFS после использования

perreal
источник
3
извините, но я перенес свою галочку на sputnick, несмотря на то, что вам больше понравился ваш вариант, просто потому, что я узнал о функции printf.
Аксель Брегнсбо
3
Спасибо за этот ответ - мне это нравится! Слишком плохие назначения происходят после расширения, поэтому IFS=$'\n' echo "${my_array[*]}"не работает. Ну что ж!
cxw
@cxw, что ты имеешь в виду под "назначениями"?
Стивен Шоу
1
@bschlueter, я пробовал с Bash 4 - 4.4.23 (1) -релиз - и все работает!
Стивен Шоу
1
@cxw Ах, я не видел, что ты пытался там делать. Я думаю, что это не работает, потому echoчто встроен в Bash. Тем не менее, вы можете обернуть его в функцию, и она будет работать! gist.github.com/steshaw/53ba0095bce8ccab52d26a14375dedb8
Стивен Шоу,
40

Использование для :

for each in "${alpha[@]}"
do
  echo "$each"
done

Использование истории ; обратите внимание, что это не удастся, если ваши значения содержат !:

history -p "${alpha[@]}"

Использование базового имени ; обратите внимание, что это не удастся, если ваши значения содержат /:

basename -a "${alpha[@]}"

Использование shuf ; обратите внимание, что результаты могут не соответствовать порядку:

shuf -e "${alpha[@]}"
Стивен Пенни
источник
19
"Шуф" ... "не может выйти в порядок" ... весело.
Уолф
4
для шуфа. Кто бы мог подумать, что использовать это?
fbicknel
3

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

 # EXP_LIST2 is iterated    
 # imagine a for loop
     EXP_LIST="List item"    
     EXP_LIST2="$EXP_LIST2 \n $EXP_LIST"
 done 
 echo -e $EXP_LIST2

хотя это добавило пробел к списку, что нормально - я хотел, чтобы он немного отступил. Также предположим, что «\ n» может быть напечатано в оригинальном $ EP_LIST.

wuxmedia
источник
5
Не похоже на полный пример.
Кенорб
3

Еще одним полезным вариантом является труба для tr:

echo "${my_array[@]}" | tr ' ' '\n'

Это выглядит просто и компактно

0x00
источник
11
За исключением этого перерывыmy_array=( "one two" three )
Майк Холт
Исправлено с двойными кавычками.
Стивен Шоу
Не работал так, как рекламируется в Bash версии 4+, пришлось использовать echo "${my_array[@]}" | tr '' ' \n', хотя лично я бы избегал echoтакого использования , где trмой выбор, я думаю, что-то вроде этого tr '' ' \n' <<<"${my_array[@]}"может быть немного легче читать позже.
S0AndS0