Czy drukować elementy tablicy na osobnych liniach w Bash?

229

Jak wydrukować element tablicy tablicy Bash na osobnych liniach? Ten działa, ale na pewno istnieje lepszy sposób:

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

Próbowałem tego, ale to nie działało:

$ IFS=$'\n' echo ${my_array[*]}
one two three
Axel Bregnsbo
źródło

Odpowiedzi:

436

Spróbuj to zrobić:

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

Różnica między $@i $*:

  • Nieokreślone wyniki są nieokreślone. W Bash, oba rozwijają się do oddzielnych argumentów, a następnie podświetlane i globowane.

  • Przytoczony, "$@"rozwija każdy element jako osobny argument, podczas gdy "$*" rozwija się do argumentów scalonych w jeden argument: "$1c$2c..."(gdzie cjest pierwszy znak IFS).

Prawie zawsze chcesz "$@". To samo dotyczy "${arr[@]}".

Zawsze je cytuj!

Gilles Quenot
źródło
5
I zauważ, że podwójne cudzysłowy wokół odwołania do zmiennej są ważne, jeśli chcesz się upewnić, że elementy z wewnętrznymi spacjami nie zostaną przypadkowo podzielone.
danfuzz
4
@sputnick: nie działa, elementy tablicy kończą się w jednym wierszu
Axel Bregnsbo
1
Jakie są dwa łączniki po poleceniu? W podręczniku nie znalazłem żadnych odniesień do tego.
joanpau
3
Czy istnieje sposób na to, aby nie wyświetlał żadnych pustych linii, jeśli nie ma elementów w tablicy bez konieczności | grep -v '^$'?
Noel Yap
2
@espaciomore '% s \ n' jest formatem wyjściowym funkcji printf. % s oznacza symbol zastępczy argumentu łańcucha (w tym przypadku element tablicy), a następnie \ n dodaje podział wiersza. W związku z tym w danych wyjściowych dla każdego elementu w tablicy wystąpi ciąg znaków i podział wiersza.
Koja
71

Wystarczy podać argument do echa:

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

podpowłoka pomaga przywrócić IFS po użyciu

perreal
źródło
3
przepraszam perreal, przesunąłem znacznik wyboru do sputnick, mimo że bardziej lubię twoje rozwiązanie, tylko dlatego, że poznałem funkcję „printf”.
Axel Bregnsbo
3
Dzięki za odpowiedź - podoba mi się! Po rozszerzeniu zdarzają się złe zadania, więc IFS=$'\n' echo "${my_array[*]}"nie działa. No cóż!
cxw
@cxw, co rozumiesz przez „zadania się zdarzają”?
Steven Shaw,
1
@ bschlueter, próbowałem z Bash 4 - 4.4.23 (1) - wydanie - i działa!
Steven Shaw
1
@ cxw Ah, nie widziałem, co próbujesz tam zrobić. Myślę, że to nie działa, ponieważ echojest wbudowane w Bash. Możesz jednak zawinąć go w funkcję i zadziała! gist.github.com/steshaw/53ba0095bce8ccab52d26a14375dedb8
Steven Shaw
40

Używanie do :

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

Korzystanie z historii ; zauważ, że to się nie powiedzie, jeśli twoje wartości zawierają !:

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

Korzystanie z basename ; zauważ, że to się nie powiedzie, jeśli twoje wartości zawierają /:

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

Korzystanie z shuf ; pamiętaj, że wyniki mogą nie zostać wyświetlone w kolejności:

shuf -e "${alpha[@]}"
Steven Penny
źródło
19
„shuf”… „może nie wyjść w kolejności”… przezabawne.
Walf
4
dla shuf. Kto by pomyślał, aby z tego skorzystać?
fbicknel
3

Próbowałem tutaj odpowiedzi w gigantycznym ... for loop, ale nie miałem żadnej radości - więc zrobiłem to w ten sposób, może niechlujny, ale wykonałem robotę:

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

chociaż to dodało spację do listy, co jest w porządku - chciałem, żeby było trochę wcięte. Załóżmy również, że „\ n” może być wydrukowane w oryginalnej $ EP_LIST.

wuxmedia
źródło
5
Nie wygląda na kompletny przykład.
kenorb
3

Innym przydatnym wariantem jest potok do tr:

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

Wygląda to prosto i kompaktowo

0x00
źródło
11
Z wyjątkiem tych przerwmy_array=( "one two" three )
Mike Holt
Naprawiono to z podwójnymi cudzysłowami.
Steven Shaw,
Nie działał tak, jak reklamowano w wersji Bash 4+, musiałem go użyć echo "${my_array[@]}" | tr '' ' \n', chociaż osobiście unikałbym echotakiego używania , w którym trmoim zdaniem coś podobnego tr '' ' \n' <<<"${my_array[@]}"może być nieco łatwiejsze do przeczytania później.
S0AndS0