Все переменные хранятся в памяти как строка в bash?

14

Скажем, я создал следующие переменные:

s=John
i=12345
f=3.14

Все эти переменные хранятся в памяти в виде строки или bashимеют другие типы данных?

user268325
источник
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.

Ссылки:

roaima
источник
13

Bash по существу имеет простые скалярные переменные, массивы и ассоциативные массивы. Кроме того, скаляры могут быть помечены как целые числа с помощью declareвстроенной функции . С точки зрения программиста скрипта / пользователя оболочки строковые переменные действуют как строки, целочисленные переменные действуют как целые числа, и массивы соответствуют их типу. Внутренняя реализация не очень актуальна.


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

В Bash 4.4 скаляры хранятся в виде строк независимо от целочисленного тега. Это видно в определении struct variable/ SHELL_VARtypedef и в функцииmake_variable_value , которая явно переводит целые числа в строки для хранения.

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

Тем не менее, код также содержит определение для неиспользуемыхunion _value , с полями для целых чисел, чисел с плавающей запятой, а также строковых значений. Он отмечен в комментарии как «на будущее», поэтому возможно, что какая-то будущая версия Bash будет хранить различные типы скаляров в их собственных формах.

ilkkachu
источник
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внутреннее представление изменяется с флагами атрибутов, строки - это все, что видит или хочет видеть bash.

bu5hman
источник
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. Вы можете вникнуть в исходный код реализации и проверить, какое представление оно выберет, но это может изменить представление завтра в следующем выпуске патча, и у вас не будет возможности узнать об этом.
Йорг Миттаг
Переменные Шредингера? Я согласен с вами в основном в том, что базовое представление не имеет значения (см. Мой ответ), но при использовании bash мы фактически «кодируем интерфейс», и представление в интерфейсе является неровным.
bu5hman
2
Да, но речь идет не о представлении на границе раздела, а конкретно о том , как они «хранятся в памяти». И на этот вопрос я бы ответил: мы не знаем, не можем и не должны знать.
Йорг Миттаг
Который перефразирует последнюю строку моего собственного поста ..... как я уже сказал, мы согласны ...... и учитывая представителя ОП и характер вопроса, я думаю, что они получат разумные оценки за свою домашнюю работу, кто бы ни получает цитату ;-).
bu5hman