¿Todas las variables se almacenan en la memoria como una cadena en bash?

14

Digamos que creé las siguientes variables:

s=John
i=12345
f=3.14

¿Todas estas variables se almacenan en la memoria como una cadena o bashtienen otros tipos de datos?

usuario268325
fuente
1
Solo por interés, ¿por qué importaría? Realmente no podría importarme menos si se almacenaron como texto swahili siempre que no afecte la funcionalidad del idioma (afectar el rendimiento puede ser un problema, pero, si eso es importante, son mejores herramientas en su arsenal que bash)
2
@paxdiablo No importa, solo pregunto por curiosidad, ya que todos los demás lenguajes de programación / scripting que conozco (por ejemplo: Java, C ++, JavaScript, PHP, etc.) tienen una representación de memoria única para cada tipo de datos , por lo que es interesante ver un lenguaje de secuencias de comandos que solo tiene una representación de memoria para todos los tipos de datos.
user268325

Respuestas:

16

Las variables Bash no están tipificadas .

A diferencia de muchos otros lenguajes de programación, Bash no segrega sus variables por "tipo". Esencialmente, las variables de Bash son cadenas de caracteres, pero, según el contexto, Bash permite operaciones aritméticas y comparaciones de variables. El factor determinante es si el valor de una variable contiene solo dígitos.

Como dice otra respuesta , hay una especie de forma débil de escribir con declare.

Esta es una forma muy débil de escribir [1] disponible en ciertos lenguajes de programación.

Ver un ejemplo:

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.

Referencias

roaima
fuente
13

Bash tiene esencialmente variables escalares simples, matrices y matrices asociativas. Además, los escalares se pueden etiquetar como enteros con la función declareincorporada . Desde el punto de vista del programador del script / usuario de shell, las variables de cadena actúan como cadenas, las variables enteras actúan como enteros y las matrices de acuerdo con su tipo. La implementación interna no es muy relevante.


Pero, si deseamos saber cómo se almacenan realmente los datos en la memoria, debemos examinar el código fuente para ver qué hace realmente el programa.

En Bash 4.4, los escalares se almacenan como cadenas, independientemente de la etiqueta entera. Esto es visible en la definición de struct variable/ SHELL_VARtypedef y en la funciónmake_variable_value , que traduce explícitamente enteros a cadenas para el almacenamiento.

Las matrices se almacenan en lo que parece ser una lista vinculada ( array.h) y las matrices asociativas como tablas hash. Los valores dentro de ellos se almacenan nuevamente como cadenas. La elección de una lista vinculada para las matrices puede parecer extraña, pero como las matrices pueden ser escasas y los índices pueden ser números arbitrarios independientemente de la cantidad de elementos que contenga la matriz, esa elección de diseño es un poco más fácil de entender.

Sin embargo, el código también contiene una definición para lo no utilizadounion _value , con campos para números enteros, números de coma flotante, así como valores de cadena. Está marcado en un comentario como "para el futuro", por lo que es posible que alguna versión futura de Bash almacene diferentes tipos de escalares en sus formas nativas.

ilkkachu
fuente
1

Por mi vida, no puedo encontrar esto en ninguna parte con tantas palabras, pero así es como lo entiendo.

Bash es un intérprete, no un compilador y representa todas las variables como cadenas. De ahí todo el esfuerzo y énfasis que conlleva las expansiones de varios tipos.

Bash pasa pasa todas las variables con nombre que declarecomo cadenas con atributos que el control de la forma en que la variable se va ampliado por declareel almacenamiento.

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

Y por supuesto

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

La clave para esto es que, incluso si declaretiene una representación interna que cambia con las banderas de atributos, las cadenas son todo lo que bash ve o quiere ver.

bu5hman
fuente
0

Es irrelevante.

La única forma de interactuar con las variables de Bash es a través de Bash, por lo que es imposible que note alguna diferencia en cuanto a cómo se almacenan las variables en la memoria, ya que nunca puede acceder a ellas a través de la memoria directamente , siempre debe preguntarle a Bash por su valor, y Bash luego puede traducirlos de la forma en que quiera verse como si hubieran sido almacenados de una manera específica.

De hecho, es posible que ni siquiera se pueden almacenar en la memoria en absoluto . No sé cuán inteligentes son las implementaciones comunes de Bash, pero al menos es posible en casos simples determinar si se usará una variable y / o si se modificará, y optimizarla por completo o alinearla.

Jörg W Mittag
fuente
Creo que el punto de la pregunta era la representación más que la ubicación
bu5hman el
2
Mi punto es que no puedes conocer la representación, porque no puedes observarla. Por lo tanto, es irrelevante y puede cambiar sin que te des cuenta. Es simplemente imposible saber qué representación podría elegir Bash. Podría profundizar en el código fuente de una implementación y verificar qué representación elige, pero podría cambiar la representación mañana en la próxima versión del parche y no habría forma de que lo supiera.
Jörg W Mittag el
¿Variables de Schroedingers? Estoy de acuerdo con usted fundamentalmente en que la representación subyacente es irrelevante (vea mi respuesta), pero al usar bash efectivamente estamos 'codificando a una interfaz' y la representación en la interfaz es fibrosa.
bu5hman el
2
Sí, pero la pregunta no es sobre la representación en el límite de la interfaz, sino específicamente sobre cómo se "almacenan en la memoria". Y a esa pregunta, respondería: no, no podemos y no debemos saber.
Jörg W Mittag el
Lo que parafrasea la última línea de mi propia publicación ... como dije, estamos de acuerdo ... y dado el representante de los OP y la naturaleza de la pregunta, creo que recibirán calificaciones razonables por su tarea, quienquiera que sea se cita ;-).
bu5hman el