2016-08-18 6 views
1

дурачиться в Bash (просто для удовольствия) и обнаружил, что вы можете ссылаться на массив и получаете свое значение от имени переменного:Получить индекс массива от имени

[email protected]:~$ ARR=(one two); 
[email protected]:~$ ARRAYINDIRECT="ARR[@]" 
[email protected]:~$ echo "${!ARRAYINDIRECT}" 
one two 

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

[email protected]:~$ ARR=(one two); echo "${!ARR[@]}" 
0 1 

, но я не могу найти правильный синтаксис для этого. Вот несколько способов, я пытался:

[email protected]:~$ ARR=(one two); ARRAYINDIRECT="ARR[@]"; echo "${!!ARRAYINDIRECT}" 
bash: !ARRAYINDIRECT}: event not found 

ARR=(one two); ARRAYINDIRECT="!ARR[@]"; echo "${!ARRAYINDIRECT}" 
bash: !ARR[@]: event not found 

# Increasingly desperate attempts... 
[email protected]:~$ ARR=(one two); ARRAYINDIRECT="\!ARR[@]"; echo "${!ARRAYINDIRECT}" 

[email protected]:~$ ARR=(one two); ARRAYINDIRECT="ARR[@]"; echo "${!${!ARRAYINDIRECT}}" 
bash: ${!${!ARRAYINDIRECT}}: bad substitution 
[email protected]:~$ ARR=(one two); ARRAYINDIRECT="ARR[@]"; echo "${\!!ARRAYINDIRECT}" 
bash: !ARRAYINDIRECT}: event not found 
[email protected]:~$ ARR=(one two); ARRAYINDIRECT="ARR[@]"; echo "${!\!ARRAYINDIRECT}" 
bash: ${!\!ARRAYINDIRECT}: bad substitution 

Вопрос: возможно получить массив индексов массива после ссылки по имени?

+0

@wjandrea Да, вы можете, с ответом анубхава в! Как указано из первого слова в первой строке в первом предложении, * Одурачивание в Bash (просто для удовольствия) *, поэтому это не научит меня чему-либо. Если вам нужен действительный прецедент, передача массива функции по имени - это то, что я делаю, чтобы манипулировать ими (даже работает на 'local' vars!), Поэтому было бы здорово, если бы я выполнял итерацию и сопоставлял элементы массива к другому, и я хотел сохранить структуру индекса в новом массиве. На самом деле, это было бы здорово для любых манипуляций с индексами, когда они были переданы по имени. –

ответ

2

Если вы используете BASH 4.2+, то вы можете использовать declare -n:

arr=(one two) 

declare -n arrayindirect=arr 

echo "${arrayindirect[@]}" 
one two 

echo "${!arrayindirect[@]}" 
0 1 

declare -p arrayindirect 
declare -n arrayindirect="arr" 
+1

Awesome - намного проще реализовать, чем ожидалось! –

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