Косвенный возврат всех элементов в массиве

1-й исключая сотрудником: Как я делаю (что-то тривиальное)?
2-й исключая сотрудником: sudo rm -rf /
1-й исключая сотрудником: Ха-ха хорошо
...
1-й исключая сотрудником (Забывавшим, что он был бы просто sudoредактор что-то еще, таким образом, это не попросило его пароль снова): о, F ** K!!!

9
09.03.2017, 05:09
4 ответа

Я думаю, что использование косвенной ссылки переменной удара нужно рассматривать буквально.

Например, Для Вашего исходного примера:

a=(one two three)
echo ${a[*]} # one two three
b=a
echo ${!b[*]} # this would not work, because this notation 
              # gives the indices of the variable b which
              # is a string in this case and could be thought
              # as a array that conatins only one element, so
              # we get 0 which means the first element
c='a[*]'
echo ${!c} # this will do exactly what you want in the first
           # place

Для последнего реального сценария я полагаю, что код ниже сделал бы работу.

LIST_lys=(lys1 lys2)
LIST_diaspar=(diaspar1 diaspar2)

whichone=$1   # 'lys' or 'diaspar'

_LIST="LIST_$whichone"[*]
LIST=( "${!_LIST}" ) # Of course for indexed array only 
                     # and not a sparse one

Лучше использовать нотацию "${var[@]}" которые стараются не портить с $IFS и расширение параметра. Вот заключительный код.

LIST_lys=(lys1 lys2)
LIST_diaspar=(diaspar1 diaspar2)

whichone=$1   # 'lys' or 'diaspar'

_LIST="LIST_$whichone"[@]
LIST=( "${!_LIST}" ) # Of course for indexed array only 
                     # and not a sparse one
                     # It is essential to have ${!_LIST} quoted
6
27.01.2020, 20:05

Необходимо скопировать элементы явно. Для индексного массива:

b=("${a[@]}")

Для ассоциативного массива (отмечают это a название переменной типа массив, не переменная, значение которой является названием переменной типа массив):

typeset -A b
for k in "${!a[@]}"; do b[$k]=${a[$k]}; done

Если у Вас есть имя переменной в массиве, можно использовать поэлементно метод с дополнительным шагом для получения ключей.

eval "keys=(\"\${!$name[@]}\")"
for k in "${keys[@]}"; do eval "b[\$k]=\${$name[\$k]}"; done

(Предупреждение, код в этом сообщении был введен непосредственно в браузере и не протестирован.)

8
27.01.2020, 20:05
  • 1
    Вы совершенно правы, но к сожалению, который не решает мою проблему (мой пример был слишком упрощен). Я обеспечил обновление, чтобы быть более ясным на моем намерении. –  Eric Smith 06.09.2011, 11:52
  • 2
    @Eric я думаю в ksh/bash, что Вам нужна оценка на том этапе. Посмотрите мое редактирование. –  Gilles 'SO- stop being evil' 06.09.2011, 13:21
  • 3
    +1, но согласно Вашей правовой оговорке, это на самом деле не вполне работает (последний бит кода), но только нуждается в нескольких незначительных корректировках. А именно, это должно быть \${!$name[@]} на первой строке, так, чтобы первое расширение имело только '$name', и ${!a[@]} сохраняется для оценки и того же самого в для цикла, с \${$name}. Другие две обратных косых черты, прежде чем '$k' не будут строго необходимы там также. –  krb686 31.10.2016, 01:45

${!b[*]} расширяется до индексов, используемых в массиве b.

То, что Вы хотели бы, должно быть сделано на двух шагах, таким образом, eval поможет: eval echo \${$b[*]}. (Отметьте \ который гарантирует что первое $ передаст первый шаг, переменное расширение, и будет только расширен на втором шаге со стороны eval.)

Согласно расширению параметра ! оба используется для косвенного расширения ({!a}), Имена, соответствующие префиксу (${!a*}) и Список ключей массива (${!a[*]}). Поскольку Список ключей массива имеет тот же синтаксис, поскольку Ваше намеченное косвенное expansion+array расширение элемента, позже не поддерживается, как.

2
27.01.2020, 20:05
  • 1
    ${!a} действительно расширяется до значения переменной, имя которой $a. Это скорее кратко описано в руководстве в абзаце, который начинается, “Если первый символ параметра является восклицательным знаком (!), уровень переменной абстракции представлен”. –  Gilles 'SO- stop being evil' 06.09.2011, 10:35
  • 2
    Да - @Gilles является правильным, но @manatwork, на втором чтении, я заметил это ${! вид ambigious с тех пор, если это - массив, Вы имеете дело с, поведение отличается. –  Eric Smith 06.09.2011, 11:50
  • 3
    @Gilles Вы правы на том предложении, но печально это не применяется как "Исключения к этому, является расширениями $ {! prefix*} и $ {! имя} описанный ниже". Но мой ответ является, конечно, неоднозначной путаницей, таким образом, я отредактирую его. –  manatwork 06.09.2011, 12:02

Для косвенного доступа к массивам просто добавьте [@] к косвенной переменной b = a [@] .

Если эти переменные установлены:

a=(one two three)
printf '<%s> ' "${a[@]}"; echo

Тогда это будет работать:

b="a[@]"
printf '<%s> ' "${!b}"

Или просто:

echo "${!b}"

Такой массив можно скопировать следующим образом:

newArr=( "${!b}" )

А затем напечатать:

declare -p newArr

В одном скрипте:

#!/bin/bash
a=(one two three)
echo "original array"
printf '<%s> ' "${a[@]}"; echo

echo "Indirect array with variable b=a[@]"
b="a[@]"
printf '<%s> ' "${!b}"; echo

echo "New array copied in newArr, printed with declare"
newArr=( "${!b}" )
declare -p newArr

Конечно, все вышеперечисленное скопирует неразреженный массив. Тот, в котором все индексы имеют значение.

разреженные массивы

разреженные массивы могут иметь неопределенные элементы.
Например, a [8] = 1234 определяет один элемент, а в bash от 0 до 7 не существует.

Чтобы скопировать такой разреженный массив, используйте этот метод

  1. Распечатайте старый массив:

     $ oldarr [8] = 1234 
     $ declare -p oldarr 
    declare -a oldarr = ( [8] = "1234") 
     
  2. Замените имя массива и запишите строку:

     $ str = $ (declare -p oldarr | sed 's / oldarr = / newarr = / ') 
     
  3. Оцените созданную таким образом строку, новый массив определен:

     $ eval "$ str" 
     $ declare -p newarr 
    declare -a newarr = ([8] = "1234") 
     
0
20.08.2021, 13:33

Теги

Похожие вопросы