2014-12-28 3 views
2

У меня есть этот код:переменного в Баше имени массива

#!/bin/sh 

... 

for cnumber in `seq $CNUMBER`; do 
    declare -a CAT$cnumber 
    let i=0 
    while IFS=$'\n' read -r line_data; do 
     CAT$cnumber[i]="${line_data}" 
     ((++i)) 
    done < input_file_$cnumber 
done 

Это работает, если я использую имя массива без переменного $ номера C.

Но я хочу, чтобы создать несколько массивов (CAT0, CAT1, CAT2 и т.д.) и читать строки:

из файла 'input_file_0' в массив 'CAT0'
из файла 'input_file_1' в массиве 'cAT1'
из файла 'input_file_2' в массив 'CAT2'
т.д.

Что синтаксис использовать $cnumber переменные в имени массива (cat1) и во входном имя_файле?

+0

Попробуйте Concat на номер CAT {т.е. $} номер C. Дайте мне знать, если он работает – Jigar

+0

Я думаю, вы имеете в виду 'CAT $ {cnumber}' – Jasen

ответ

1
for cnumber in `seq $CNUMBER`; do 
    declare -a CAT$cnumber 
    let i=0 
    while IFS=$'\n' read -r line_data; do 
     eval CAT$cnumber[i]='"${line_data}"' 
     ((++i)) 
    done < input_file_$cnumber 
done 

Главным образом, это добавляет слово «eval», которое заставляет bash оценивать остальную часть линии. До этого bash расширяет переменные, поэтому число CAT $ будет чем-то вроде CAT1 при вычислении строки. Имейте в виду, что «$ {line_date}» будет подвержен переменному расширению до того, как eval оценит линию, если она не будет защищена одинарными кавычками. Это может иметь неожиданные последствия, если $ line_data будет содержать пробелы. Смотрите этот упрощенный пример:

a=b 
l="hello date" 
eval $a="$l" # executes "date", has no other effect 
echo $b   # prints an empty line 
eval $a='"$l"' # sets b to "hello date" 
echo $b   # prints that: hello date 

В ответ на комментарий Этан Рейснер ниже, я добавляю другое решение, которое избегает «Eval» и вместо этого использует ссылки, которые доступны в Баш версии 4.3 или выше. В этом случае, используя ссылки предпочтительнее по той причине, Этан указал, а также, на мой взгляд, потому что это более естественно:

for cnumber in `seq $CNUMBER`; do 
    declare -a CAT$cnumber  # be sure the array is declared before ... 
    declare -n ref=CAT$cnumber # ... you declare ref to reference the array 
    let i=0 
    while IFS=$'\n' read -r line_data; do 
     ref[$i]="${line_data}" 
     ((++i)) 
    done < input_file_$cnumber 
done 
+0

Следует отметить, что использование 'eval' имеет серьезные последствия для безопасности, если только переменные не контролируются ** очень тщательно. И учитывая этот фрагмент, если массивы 'CAT ##' не должны оставаться за пределами цикла, используя построенное имя переменной, подобное этому, вероятно, совершенно бессмысленно. Также косвенная ссылка здесь, вероятно, будет работать и быть более безопасной. –

0

Во-первых, ваш притон должен быть

#!/bin/bash 

так declare - встроенный баш.

Далее используйте declare для определения элементов массива

for cnumber in `seq $CNUMBER`; do 
    declare -a CAT$cnumber 
    let i=0 
    while IFS=$'\n' read -r line_data; do 
     declare "CAT$cnumber[$i]=${line_data}" 
     ((++i)) 
    done < input_file_$cnumber 
done 
Смежные вопросы