Tham chiếu các biến mảng bash từ mảng khác


8

Tôi muốn viết một tập lệnh để tham chiếu nhiều mảng từ một mảng khác chứa các tên biến của mảng này.

Đây là mã của tôi cho đến nay:

#!/bin/bash
array1=('array1string1' 'array1string2')
array2=('array2string1' 'array2string2')

array_names=('array1' 'array2')

for a in ${array_names[@]}
do
        for b in ${a[@]}
        do
                echo $b
        done
done

Tôi muốn đầu ra quét qua cả hai mảng (từ vòng lặp for bên ngoài) và in các chuỗi tương ứng ở vòng lặp for bên trong để gọi echo. Đầu ra hiện tại của tôi chỉ cho tôi thấy:

array1
array2

Tôi sẽ biết ơn bất kỳ con trỏ liên quan đến điều này. Cảm ơn bạn!


Có bất kỳ lý do tại sao bạn không thể làm for b in "${array1[@]}" "${array2[@]}"; do ...; done?
Kusalananda

Tôi muốn số lượng mảng được linh hoạt. Do đó, nếu tôi thêm một mảng sau, tôi sẽ chỉ thêm nó vào mảng_names và để vòng lặp xử lý nó.
chnppp

Tôi nghĩ rằng đây là một trường hợp để mở rộng gián tiếp. Xem stackoverflow.com/questions/8515411/ - - về cơ bản, thay đổi ${a[@]}để ${!a}làm những gì bạn muốn (tôi nghĩ).
parkamark

1
@parkamark Không, điều đó chỉ mang lại cho anh ấy yếu tố đầu tiên của mỗi mảng. Và ${!a[@]}đưa ra một chiều dài của mảng a.
Kusalananda

Vâng, thay đổi ${!a}chỉ là cho tôi những yếu tố đầu tiên.
chnppp

Câu trả lời:


7

Bash 4.3 trở lên hỗ trợ "tham chiếu tên" hoặc namerefs (một khái niệm tương tự tồn tại ksh93, nhưng phạm vi khác nhau một cách khó chịu ):

#!/bin/bash

array1=('array1string1' 'array1string2')
array2=('array2string1' 'array2string2')

array_names=('array1' 'array2')

for a in "${array_names[@]}"; do
    declare -n arr="$a"

    for b in "${arr[@]}"; do
        echo "$b"
    done
done

Biến arrlà một nameref hoạt động như một bí danh cho biến được đặt tên (biến có tên $atrong ví dụ này).

Nếu không có namerefs, trong các phiên bản Bash trước đó, một giải pháp sẽ là tạo một mảng mới chứa tất cả các phần tử từ các mảng khác:

all=( "${array1[@]}" "${array2[@]}" )

... hơi giống với array_namesmảng trong câu hỏi nhưng với nội dung của tất cả các mảng, và sau đó lặp lại "${all[@]}".

Cũng có thể sử dụng eval, nhưng mã kết quả trông cực kỳ khủng khiếp.

Xem câu trả lời của glenn jackman cho một biến thể với biến đổi không đổi (được giới thiệu ở dạng hiện tại với Bash phiên bản 2).



0

Như một biến thể về những gì đã nói:

#!/bin/bash

array1=('array1 string1' 'array1 string2')
array2=('array2 string1' 'array2 string2')
array_names=('array1' 'array2')

for (( i=0; i<${#array_names[@]}; i++ )); do

    declare -n arr="${array_names[i]}"

    for (( j=0; j<${#arr[@]}; j++ )); do
        echo "${arr[j]}"
    done

done

Thay vào đó, truy cập các phần tử theo chỉ mục

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.