2013-11-17 2 views
0

читателей Noble StackOverflow,Bash - расширение переменной вложенных в переменной

У меня есть запятыми файл, каждая строка которого я помещаю в массив. данных выглядит так ...

25455410,GROU,AJAXa,GROU1435804437 
25455410,AING,EXS3d,AING4746464646 
25455413,TRAD,DLGl,TRAD7176202067 

Есть 103 строк, и я могу генерировать 103 массивов без проблем.

n=1; while read -r OrdLine; do 
    IFS=',' read -a OrdLineArr${n} <<< "$OrdLine" 
    let n++ 
done < $WkOrdsFile 

ОДНАКО, я могу получить доступ только массивы так ...

echo "${OrdLineArr3[0]} <---Gives 25455413 

Я не могу получить доступ к нему с номером 1-103 в качестве переменной - например, следующий не работает. ..

i=3 
echo "${OrdLineArr${i}[0]} 

Это приводит к ...

./script2.sh: line 24: ${OrdLineArr${i}[0]}: bad substitution 

Я думаю, что ответ может включать «eval», но я не могу найти подходящий пример для заимствования. Если кто-то может это исправить, то приведенный выше код упрощает обработку 2d-массива в bash!

Большое вам спасибо за помощь!

Dan

+1

Возможно дубликат http://stackoverflow.com/questions/6724056/nested-shell-parameter-expansion. – Chandranshu

+0

Bash поддерживает только одномерные массивы, и вам будет лучше использовать Perl для этой задачи. Если вам действительно нужно использовать Bash, проверьте http://tldp.org/LDP/abs/html/arrays.html конкретный пример 27.17 – MattSizzle

+0

@ruakh - косвенное расширение внутри функции обработало удовольствие. Это очень приятная парадигма для 2-х массивов, когда они вынуждены использовать bash для их обработки! Спасибо! – user3000596

ответ

0

eval, как правило, плохая идея, но вы можете сделать это с:

eval echo "\${OrdLineArr$i[0]}" 
0

Я бы хранить каждую строку в массиве, но разбить его по требованию:

readarray OrdLineArr < $WkOrdsFile 
... 
OrdLine=${OrdLineArr[i]} 
IFS=, read -a Ord <<< "$OrdLine" 

Однако bash не предназначен для обработки данных; он предназначен для облегчения процесса и управления файлами. Вы должны использовать другой язык.

1

Вы можете использовать косвенное расширение. Например, если $key - OrdLineArr4[7], то ${!key} (с восклицательным знаком) означает ${OrdLineArr4[7]}. (См §3.5.3 "Shell Parameter Expansion" in the Bash Reference Manual, хотя надо признать, что проход не объясняет, как косвенное расширение взаимодействует с массивами.)

Я рекомендовал бы оборачивая в функции:

function OrdLineArr() { 
    local -i i="$1"   # line number (1-103) 
    local -i j="$2"   # field number (0-3) 
    local key="OrdLineArr$i[$j]" 
    echo "${!key}" 
} 

Тогда вы можете написать:

echo "$(OrdLineArr 3 0)"  # prints 25455413 
i=3 
echo "$(OrdLineArr $i 0)"  # prints 25455413 

Это, очевидно, не полная замена двумерных массивов, но она выполнит то, что вам нужно. Без использования eval.

+0

Это, безусловно, лучший ответ, но инструкция 'echo' в конце функции' OrdLineArr' будет удалять завершающие символы новой строки, если таковые имеются. Если это вызывает беспокойство, используйте глобальную переменную для возвращаемого значения этой функции, например, 'OrdLineArr_ret = $ {! Key}'. –

+0

Еще один быстрый комментарий, вы можете получить доступ к полному массиву с помощью 'aryp = OrdLineArr [@]': тогда '' $ {! Aryp} "' будет расширяться до полного массива. –

+0

@gniourf_gniourf: Re: trailing newlines: Да, я подумал об этом (это одна из причин, почему я не считаю это полной заменой для двумерных массивов), но массив OP явно не будет иметь новых строк в своих элементах, поэтому я счел это в порядке – ruakh

Смежные вопросы