Чи всі змінні зберігаються в пам'яті як рядки в bash?


14

Скажіть, я створив такі змінні:

s=John
i=12345
f=3.14

Чи всі ці змінні зберігаються в пам'яті як рядкові, чи bashє інші типи даних?


1
Просто з інтересу, чому це має значення? Мені справді було б менше байдуже, якщо вони зберігаються як суахілістський текст, якщо це не впливає на функціональність мови (це може вплинути на продуктивність, але, якщо це важливо, вони є кращими інструментами у вашому арсеналі, ніж bash).

2
@paxdiablo Це не має значення, я просто запитую від цікавості, оскільки всі інші мови програмування / сценаріїв, які я знаю (наприклад: Java, C ++, JavaScript, PHP тощо), мають унікальне представлення пам'яті для кожного типу даних , тому цікаво бачити мову сценаріїв, яка має лише одне представлення пам'яті для всіх типів даних.
user268325

Відповіді:


16

Змінні Bash не типізовані .

На відміну від багатьох інших мов програмування, Bash не відокремлює свої змінні за "типом". По суті, Bash змінні - це символьні рядки, але, залежно від контексту, Bash дозволяє арифметичні операції та порівняння змінних. Визначальним фактором є те, чи містить значення змінної лише цифри.

Як говорить інша відповідь , існує якась слабка форма набору тексту declare.

Це дуже слабка форма набору тексту [1], доступна в певних мовах програмування.

Дивіться приклад:

declare -i number
# The script will treat subsequent occurrences of "number" as an integer.     

number=3
echo "Number = $number"     # Number = 3

number=three
echo "Number = $number"     # Number = 0
# Tries to evaluate the string "three" as an integer.

Список літератури:


13

Bash по суті має прості скалярні змінні, масиви та асоціативні масиви. Крім того, скаляри можуть бути позначені цілими числами з declareвбудованим . З точки зору користувача програміста сценарію / оболонки, струнні змінні виступають як рядки, цілі змінні діють як цілі числа, і масиви відповідно до їх типу. Внутрішня реалізація не дуже актуальна.


Але, якщо ми хочемо знати, як дані насправді зберігаються в пам'яті, ми повинні вивчити вихідний код, щоб побачити, що насправді робить програма.

У Bash 4.4 скаляри зберігаються як рядки незалежно від цілого тегу. Це видно у визначенні struct variable/ SHELL_VARtypedef та у функціїmake_variable_value , яка явно переводить цілі числа до рядків для зберігання.

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

Однак код також містить визначення невикористаногоunion _value з полями для цілих чисел, чисел з плаваючою комою, а також значень рядків. У коментарі це позначено як "на майбутнє", тому можливо, що деяка майбутня версія Bash зберігатиме різні типи скалярів у рідних формах.


1

За все життя я не можу знайти це ніде сказане так багато слів, але це я так розумію.

Bash - інтерпретатор, а не компілятор і представляє всі змінні як рядки. Звідси всі зусилля та акценти, що пов'язані з різними розширеннями.

Bash передає передає всі імена змінних в declareвигляді рядків з атрибутами , які контролюють , як ця змінна повинна бути розширена шляхом declareпри зберіганні.

banana=yellow              #no call to declare
declare -p banana
declare -- banana="yellow" #but declare was invoked with --

declare -i test=a          #arithmetic expansion to null/zero
declare -p test
declare -i test="0"

declare -i test2=5+4       #successful arithmetic expansion
declare -p test2
declare -i test2="9"

declare -i float=99.6      #arithmetical expansion fails due to syntax
bash: declare: 99.6: syntax error: invalid arithmetic operator (error token is ".6")

nofloat=99.9
declare -p nofloat
declare -- nofloat"99.6"   #Success because arithmetical expansion not invoked

declare -a a               #variable is marked as a placeholder to receive an array
declare -p a
declare -a a

a[3]=99                    #array elements are appended
a[4]=99
declare -p a
declare -a a=([3]="99" [4]="99") 

declare -A newmap          #same as -a but names instead of numbers
newmap[name]="A Bloke"
newmap[designation]=CFO
newmap[company]="My Company"
declare -p newmap
declare -A newmap=([company]="My Company" [name]="A Bloke" [designation]="CFO" )

І звичайно

declare -ia finale[1]=9+16
declare -p finale
declare -ai finale=([1]="25")

Кода до цього полягає в тому, що навіть якщо declareє внутрішнє представлення, яке змінюється прапорами атрибутів, рядки - це все, що баш бачить або хоче бачити.


0

На цій сторінці є вичерпний посібник із введення змінних у Bash. У цьому розділі є додаткова інформація про declareвбудовану команду. Цей фрагмент коду з цього посилання може зацікавити:

[bob in ~] declare -i VARIABLE=12

[bob in ~] VARIABLE=string

[bob in ~] echo $VARIABLE
0

[bob in ~] declare -p VARIABLE
declare -i VARIABLE="0"

Ось manсторінка дляdeclare .


0

Це не має значення.

Єдиний спосіб взаємодії зі змінними Bash - це через Bash, тому неможливо помітити будь-яку різницю щодо того, як змінні зберігаються в пам'яті, тому що ви ніколи не можете отримати доступ до них через пам'ять безпосередньо , вам завжди потрібно запитати у Bash їх значення, і Bash може потім перевести їх в який би шлях він хоче виглядати , як якщо б вони були збережені в будь-якому певним чином.

Насправді, вони не можуть навіть бути збережені в пам'яті у всіх . Я не знаю, наскільки розумні загальні реалізації Bash, але принаймні в простих випадках можна визначити, чи буде використовуватися змінна та / або чи буде вона модифікована, і повністю її оптимізувати чи вбудовувати.


Я думаю, що питанням було питання про представництво, а не про місце
bu5hman

2
Моя думка полягає в тому, що ви не можете знати представництво, оскільки ви не можете його спостерігати. Отже, це не має значення і може змінитися, не помічаючи ніколи. Неможливо сказати, яке представлення може вибрати Bash. Ви можете заглибитися у вихідний код реалізації та перевірити, яке представництво воно обрало, але воно може змінити представлення завтра в наступному випуску патчу, і вам не було б відомо про це.
Йорг W Міттаг

Змінні Шродиндера? Я погоджуюся з вами принципово, що базове представлення не має значення (див. Мою відповідь), але, використовуючи bash, ми ефективно «кодуємо інтерфейс», а представлення на інтерфейсі є складним.
bu5hman

2
Так, але питання не в поданні на межі інтерфейсу, а конкретно в тому, як вони "зберігаються в пам'яті". І на це питання я би відповів: ми цього не можемо, не можемо і не повинні.
Йорг W Міттаг

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