Чи підтримує bash підтримку використання покажчиків?


12

Просте запитання. Чи має bash оболонка підтримку використання покажчиків під час написання сценарію оболонки?

Мені знайоме позначення розширення ${var[@]}при ітерації над масивом $var, але незрозуміло, що це використання покажчиків для ітерації над індексами масиву. Чи надає bash доступ до адрес пам'яті, як і інші мови?

Якщо bash не підтримує використання покажчиків, що робити інші оболонки?

Відповіді:


28

Вказівник (на місце пам'яті ) насправді не є корисною концепцією в чомусь вищому рівні, ніж C, будь то щось на зразок Python або оболонки. Посилання на об'єкти, звичайно, корисні в мовах високого рівня, можливо, навіть необхідні для побудови складних структур даних. Але в більшості випадків мислення з точки зору адреси пам'яті є занадто низьким рівнем, щоб бути дуже корисним.

У Bash (та інших оболонках) ви можете отримати значення елементів масиву з ${array[index]}позначеннями, призначити їх array[index]=...і отримати кількість елементів у масиві ${#array[@]}. Вираз всередині дужок є арифметичним виразом. Як складений приклад, ми можемо додати постійний префікс для всіх членів масиву:

for ((i=0 ; i < ${#array[@]} ; i++ )) ; do
    array[i]="foo-${array[i]}"
done

(Якби ми дбали лише про значення, а не про індекси, просто for x in "${array[@]}" ; do...було б добре.)

З асоціативними або розрідженими масивами числовий цикл не має особливого сенсу, але замість цього нам потрібно буде отримати ключі / індекси масиву ${!array[@]}. Напр

declare -A assoc=([foo]="123" [bar]="456")
for i in "${!assoc[@]}" ; do 
    echo "${assoc[$i]}"
done 

На додаток до цього, Bash має два способи опосередковано вказати на іншу змінну:

  • непряме розширення , використовуючи в ${!var}синтаксис , який використовує значення змінної, ім'я в var, і
  • namerefs , які потрібно створити за допомогою declareвбудованого (або ksh-сумісного синоніма, typeset). declare -n ref=varробить refпосилання на змінну var.

Namerefs також підтримують індексацію в тому випадку, якщо ми arr=(a b c); declare -n ref=arr;тоді ${ref[1]}будемо розширюватися до b. Використання ${!p[1]}замість цього взяти pяк масив, і посилатися на змінну з ім'ям його другим елементом.

У Bash, namerefs буквально те, що посилання на ім’я та використання nameref зсередини функції використовуватиме місцеве значення названої змінної. Це надрукується local value of var.

#!/bin/bash
fun() {
        local var="local value of var"
        echo "$ref";
}
var="global var"
declare -n ref=var
fun

BashFAQ також має більш довгу статтю про непрямість .


2
непрямість досить корисна для мов вищого рівня. наприклад, посилання в perl. Вони не такі, як покажчики С, але вони виконують ту саму основну функцію. Навіть bash може отримувати доступ до змінних побічно ... але IMO, якщо ви почнете писати код, який істотно використовує цю функцію, вам краще почати з нуля з perl або чогось іншого. Дивіться також mywiki.wooledge.org/BashFAQ/006
cas

2
@cas, о, абсолютно. Але, напевно, краще думати про них як на вказівку на об’єкти , а не на адреси пам'яті. (Навіть у C, є такий тип.) Я мав на увазі зазначити як непряме розширення, так і назви, але не встиг це зробити негайно.
ilkkachu

Напевно, варто зазначити, що приклад for-loop написаний природніше, for foo in "${array[@]}" ; do ... doneякщо індекс не потрібен для інших цілей.
Буде Кроуфорд

@WillCrawford, крапка. редагував приклад і зазначив.
ilkkachu

9

Ні, bashне має "покажчиків", але в ньому є посилання:

$ spam="fred"
$ declare -n tripe=spam
$ echo $tripe
fred
$ tripe=juki
$ echo $spam
juki

На bashчоловіковій сторінці:

Змінній може бути призначений атрибут nameref, використовуючи параметр -n командам declareабо localвбудований для створення імені refre або посилання на іншу змінну. Це дозволяє непрямим чином маніпулювати змінними. Щоразу, коли на змінну nameref посилається, призначається, не встановлюється чи змінюються його атрибути (крім використання або зміни самого атрибута nameref), операція фактично виконується на змінній, визначеній значенням змінної nameref. Ім'яреф зазвичай використовується у функціях оболонки для позначення змінної, ім'я якої передається як аргумент функції. Наприклад, якщо ім'я змінної передається функції оболонки як її перший аргумент, запущений

declare -n ref=$1

всередині функції створюється переменная nameref ref, значенням якої є назва змінної, передана як перший аргумент. Посилання та призначення для перегляду та зміни його атрибутів трактуються як посилання, призначення та зміни атрибутів змінної, ім'я якої передано як 1 долар. Якщо контрольна змінна в циклі for for має атрибут nameref, у списку слів може бути список змінних оболонок, а посилання на ім’я буде встановлено для кожного слова у списку, у свою чергу, коли цикл виконується. Змінній масиву не можна надати атрибут nameref. Однак змінні nameref можуть посилатись на змінні масиву та на підписані масиви змінних. Namerefs можна відключити, використовуючи unsetвбудований параметр -n . Інакше, якщоunset виконується з ім'ям змінної nameref як аргументом, змінна, на яку посилається змінна nameref, буде знята.


4

Ні, оболонки не використовують "покажчики" (як зрозуміло на С).

Масиви можуть використовувати індекси: echo "${array[2]}"але @у вашому прикладі насправді не є "покажчиком". Це спосіб виразити "список значень масиву". Щось, що аналізатор оболонки розуміє. Подібно до способу:

$ echo "$@"

розширюється до всіх списку "Позиційні параметри".


2

У той час як масиви з індексованими bash цілими числами можна визначити та отримати доступ до нього ітераційно;

declare -a obj
obj+=("val1")
obj+=("val2")

for item in ${obj[@]}; do
  echo "${obj[${item}]} ${item}"
done

Асоціативні або строкові індексовані масиви в bash потребують наступного ітеративного визначення;

declare -A obj
obj["key1"]="val1"
obj["key2"]="val2"

for item in ${!obj[@]}; do
  echo "${obj[${item}]} ${item}"
done

Відповісти на запитання щодо покажчиків та використання одного з bash; Внутрішня функціональність компільованого бінарного двійкового файла дійсно використовує покажчики на пам'ять, виділену на стеку, і виявляє подібну функціональність з використанням eval. Див. [Непрямі посилання] http://tldp.org/LDP/abs/html/ivr.html )

Будуть дракони; використання evalслід застосовувати обережно через наслідки безпеки

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.