Todas as variáveis ​​são armazenadas na memória como string no bash?

13

Digamos que eu criei as seguintes variáveis:

s=John
i=12345
f=3.14

Todas essas variáveis ​​são armazenadas na memória como string ou bashtêm outros tipos de dados?

user268325
fonte
1
Apenas por interesse, por que isso importa? Eu realmente não poderia me importar menos se eles fossem armazenados como texto em suaíli, desde que não afetassem a funcionalidade do idioma (afetar o desempenho pode ser um problema, mas, se isso é importante, são ferramentas melhores no seu arsenal do que bash)
2
@paxdiablo Não importa, estou apenas perguntando por curiosidade, pois todas as outras linguagens de programação / script que eu conheço (por exemplo: Java, C ++, JavaScript, PHP, etc.) têm uma representação de memória exclusiva para cada tipo de dados , é interessante ver uma linguagem de script que tenha apenas uma representação de memória para todos os tipos de dados.
precisa saber é o seguinte

Respostas:

16

As variáveis ​​bash são sem tipo .

Ao contrário de muitas outras linguagens de programação, o Bash não segrega suas variáveis ​​por "tipo". Essencialmente, as variáveis ​​do Bash são cadeias de caracteres, mas, dependendo do contexto, o Bash permite operações aritméticas e comparações de variáveis. O fator determinante é se o valor de uma variável contém apenas dígitos.

Como outra resposta diz , existe uma forma fraca de digitação declare.

Esta é uma forma muito fraca da digitação [1] disponível em certas linguagens de programação.

Veja um exemplo:

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.

Referências:

roaima
fonte
13

O Bash possui essencialmente variáveis ​​escalares simples, matrizes e matrizes associativas. Além disso, os escalares podem ser marcados como números inteiros com o declareinterno . Do ponto de vista do programador de scripts / usuário do shell, as variáveis ​​de string atuam como strings, as variáveis ​​inteiras atuam como inteiros e as matrizes de acordo com seu tipo. A implementação interna não é muito relevante.


Mas, se quisermos saber como os dados são realmente armazenados na memória, devemos examinar o código-fonte para ver o que o programa realmente faz.

No Bash 4.4, os escalares são armazenados como seqüências de caracteres, independentemente da marca inteira. Isso é visível na definição de struct variable/ the SHELL_VARtypedef e na funçãomake_variable_value , que converte explicitamente números inteiros em seqüências de caracteres para armazenamento.

Matrizes são armazenadas no que parece ser uma lista vinculada ( array.h) e matrizes associativas como tabelas de hash. Os valores dentro deles são novamente armazenados como seqüências de caracteres. A escolha de uma lista vinculada de matrizes pode parecer estranha, mas como as matrizes podem ser esparsas e os índices podem ser números arbitrários, independentemente do número de elementos que a matriz contém, essa opção de design é um pouco mais fácil de entender.

No entanto, o código também contém uma definição para o não utilizadounion _value , com campos para números inteiros, números de ponto flutuante e valores de sequência. Ele está marcado em um comentário como "para o futuro", portanto, é possível que alguma versão futura do Bash armazene diferentes tipos de escalares em suas formas nativas.

ilkkachu
fonte
1

Pela minha vida, não consigo encontrar isso em nenhum lugar em tantas palavras, mas é assim que eu o entendo.

Bash é um intérprete, não um compilador e representa todas as variáveis ​​como strings. Daí todo o esforço e ênfase que acompanham as expansões de vários tipos.

Bash passa passa todas as variáveis nomeadas para declarecomo cordas com atributos que controlam como essa variável deve ser expandida por declareno armazenamento.

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" )

E claro

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

A coda disso é que, mesmo que declaretenha uma representação interna que mude com os sinalizadores de atributo, as strings são tudo o que o bash vê ou deseja ver.

bu5hman
fonte
0

Esta página possui um guia completo sobre como digitar variáveis ​​no Bash. Esta seção tem mais informações sobre o declarecomando interno. Este snippet de código desse link pode ser interessante:

[bob in ~] declare -i VARIABLE=12

[bob in ~] VARIABLE=string

[bob in ~] echo $VARIABLE
0

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

Aqui está a manpágina paradeclare .

Tanner Babcock
fonte
0

Isso é irrelevante.

A única maneira de interagir com as variáveis ​​do Bash é através do Bash, por isso é impossível notar qualquer diferença quanto à forma como as variáveis ​​são armazenadas na memória, porque como você nunca pode acessá-las diretamente através da memória , sempre solicite ao Bash valor e Bash pode então traduzi-los de qualquer maneira que ele quer olhar como se eles tinham sido armazenados em qualquer forma específica.

Na verdade, eles não podem sequer ser armazenadas na memória em tudo . Não sei quão inteligentes são as implementações comuns do Bash, mas é pelo menos possível em casos simples determinar se uma variável será usada e / ou se será modificada e otimizá-la completamente ou incorporá-la.

Jörg W Mittag
fonte
Eu acho que o ponto da questão era a representação em vez da localização
bu5hman
2
O que quero dizer é que você não pode conhecer a representação, porque não pode observá-la. Portanto, é irrelevante e pode mudar sem que você perceba. É simplesmente impossível dizer qual representação Bash pode escolher. Você pode se aprofundar no código fonte de uma implementação e verificar qual representação ela escolhe, mas isso pode mudar a representação amanhã no próximo lançamento de patch e não há como você saber.
Jörg W Mittag 01/01
Variáveis ​​de Schroedingers? Eu concordo fundamentalmente com você sobre a irrelevância da representação subjacente (veja minha resposta), mas ao usar o bash estamos efetivamente 'codificando para uma interface' e a representação na interface é exigente.
bu5hman
2
Sim, mas a questão não é sobre a representação nos limites da interface, mas especificamente sobre como eles são "armazenados na memória". E a essa pergunta, eu responderia: não sabemos, não podemos e não devemos saber.
Jörg W Mittag 01/01
O que parafraseia a última linha do meu próprio post ..... como eu disse, nós concordamos ...... e dado o representante dos OPs e a natureza da pergunta, acho que eles receberão notas razoáveis ​​pelo dever de casa, quem quer que seja é citado ;-).
bu5hman