In các phần tử mảng trên các dòng riêng biệt trong Bash?


229

Làm cách nào để in phần tử mảng của mảng Bash trên các dòng riêng biệt? Điều này hoạt động, nhưng chắc chắn có một cách tốt hơn:

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

Đã thử cái này nhưng nó không hoạt động:

$ IFS=$'\n' echo ${my_array[*]}
one two three

Câu trả lời:


436

Hãy thử làm điều này:

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

Sự khác biệt giữa $@$*:

  • Không được trích dẫn, kết quả là không xác định. Trong Bash, cả hai mở rộng để tách các đối số và sau đó là wordsplit và toàn cầu.

  • Được trích dẫn, "$@"mở rộng mỗi phần tử dưới dạng một đối số riêng biệt, trong khi "$*" mở rộng thành các đối số được hợp nhất thành một đối số: "$1c$2c..."(trong đó clà char đầu tiên của IFS).

Bạn hầu như luôn luôn muốn "$@". Cùng đi cho "${arr[@]}".

Luôn báo giá cho họ!


5
Và lưu ý, dấu ngoặc kép xung quanh tham chiếu biến là quan trọng nếu bạn muốn đảm bảo các phần tử có không gian bên trong không vô tình bị tách ra.
danfuzz

4
@sputnick: không hoạt động, các phần tử mảng kết thúc trên một dòng duy nhất
Axel Bregnsbo

1
Hai dấu gạch ngang sau lệnh là gì? Tôi không tìm thấy bất kỳ tài liệu tham khảo đến nó trong hướng dẫn.
joanpau

3
Có cách nào để làm cho nó xuất ra không có dòng trống nếu không có phần tử nào trong mảng mà không phải | grep -v '^$'không?
Noel Yap

2
@espaciomore '% s \ n' là định dạng cho đầu ra của hàm printf. % s có nghĩa là một trình giữ chỗ cho một đối số chuỗi (trong trường hợp này là phần tử mảng) và \ n thêm dấu ngắt dòng sau đó. Do đó, sẽ có một chuỗi và ngắt dòng trong đầu ra cho mỗi phần tử trong mảng.
Koja

71

Chỉ cần trích dẫn đối số để lặp lại:

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

shell phụ giúp khôi phục IFS sau khi sử dụng


3
xin lỗi perreal, tôi đã chuyển dấu kiểm của mình sang sputnick, mặc dù thích giải pháp của bạn hơn, chỉ vì tôi đã tìm hiểu về chức năng 'printf'.
Axel Bregnsbo

3
Cảm ơn câu trả lời này - tôi thích nó! Bài tập quá tệ xảy ra sau khi mở rộng nên IFS=$'\n' echo "${my_array[*]}"không hoạt động. Ồ tốt
cxw

@cxw, ý của bạn là "bài tập xảy ra" nghĩa là gì?
Steven Shaw

1
@bschlueter, tôi đã thử với Bash 4 - 4.4.23 (1) - miễn phí - và nó hoạt động!
Steven Shaw

1
@cxw Ah, tôi không thấy những gì bạn đang cố gắng làm ở đó. Tôi nghĩ rằng nó không hoạt động vì echolà một nội dung trong Bash. Tuy nhiên, bạn có thể gói nó trong một chức năng và nó sẽ hoạt động! gist.github.com/steshaw/53ba0095bce8ccab52d26a14375dedb8
Steven Shaw

40

Sử dụng cho :

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

Sử dụng lịch sử ; lưu ý điều này sẽ thất bại nếu giá trị của bạn chứa !:

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

Sử dụng tên cơ sở ; lưu ý điều này sẽ thất bại nếu giá trị của bạn chứa /:

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

Sử dụng shuf ; lưu ý rằng kết quả có thể không được đưa ra theo thứ tự:

shuf -e "${alpha[@]}"

19
"Shuf" ... "có thể không xuất hiện theo thứ tự" ... vui nhộn.
Walf

4
cho shuf. Ai có thể nghĩ rằng sử dụng nó?
fbicknel

3

Tôi đã thử các câu trả lời ở đây trong một người khổng lồ cho ... vòng lặp, nhưng không có được niềm vui nào - vì vậy tôi đã làm nó như thế này, có thể lộn xộn nhưng đã thực hiện công việc:

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

mặc dù điều đó đã thêm một khoảng trắng vào danh sách, điều này vẫn ổn - tôi muốn nó thụt vào một chút. Đồng thời, giả sử "\ n" có thể được in trong $ EP_LIST ban đầu.


5
Không giống như một ví dụ hoàn chỉnh.
kenorb

3

Một biến thể hữu ích khác là pipe để tr:

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

Điều này trông đơn giản và nhỏ gọn


11
Ngoại trừ giờ nghỉ nàymy_array=( "one two" three )
Mike Holt

Đã sửa nó với dấu ngoặc kép.
Steven Shaw

Không hoạt động như quảng cáo trên phiên bản Bash 4+, phải sử dụng echo "${my_array[@]}" | tr '' ' \n', mặc dù cá nhân tôi sẽ tránh sử dụng echonhư vậy, trong đó trlựa chọn của tôi tôi nghĩ rằng một cái gì đó như tr '' ' \n' <<<"${my_array[@]}"có thể dễ đọc hơn một chút sau này.
S0AndS0
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.