Tutte le variabili sono archiviate in memoria come stringa in bash?


14

Supponiamo di aver creato le seguenti variabili:

s=John
i=12345
f=3.14

Tutte queste variabili sono archiviate in memoria come stringa o bashhanno altri tipi di dati?


1
Solo per interesse, perché dovrebbe importare? Non me ne potrebbe fregare di meno se fossero archiviati come testo swahili purché non influisse sulla funzionalità della lingua (influire sulle prestazioni potrebbe essere un problema ma, se questo è importante, sono strumenti migliori nel tuo arsenale rispetto a bash).

2
@paxdiablo Non importa, sto solo chiedendo per curiosità, dal momento che tutti gli altri linguaggi di programmazione / scripting che conosco (ad esempio: Java, C ++, JavaScript, PHP, ecc.) hanno una rappresentazione di memoria unica per ogni tipo di dati , quindi è interessante vedere un linguaggio di scripting che abbia una sola rappresentazione di memoria per tutti i tipi di dati.
user268325

Risposte:


16

Le variabili di Bash non sono tipizzate .

A differenza di molti altri linguaggi di programmazione, Bash non separa le sue variabili per "tipo". In sostanza, le variabili di Bash sono stringhe di caratteri, ma, a seconda del contesto, Bash consente operazioni aritmetiche e confronti su variabili. Il fattore determinante è se il valore di una variabile contiene solo cifre.

Come dice un'altra risposta , c'è una sorta di forma debole di battitura a macchina declare.

Questa è una forma molto debole della digitazione [1] disponibile in alcuni linguaggi di programmazione.

Vedi un esempio:

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.

Riferimenti:


13

Bash ha essenzialmente semplici variabili scalari, array e array associativi. Inoltre, gli scalari possono essere etichettati come numeri interi con l' declareintegrato . Dal punto di vista dell'utente del programmatore di script / shell, le variabili stringa fungono da stringhe, le variabili intere fungono da numeri interi e le matrici di conseguenza al loro tipo. L'implementazione interna non è molto rilevante.


Ma, se vogliamo sapere come i dati sono effettivamente archiviati in memoria, dobbiamo esaminare il codice sorgente per vedere cosa fa effettivamente il programma.

In Bash 4.4, gli scalari sono memorizzati come stringhe, indipendentemente dal tag intero. Ciò è visibile nella definizione di struct variable/ SHELL_VARtypedef e nella funzionemake_variable_value , che traduce esplicitamente numeri interi in stringhe per l'archiviazione.

Gli array sono memorizzati in quello che sembra essere un elenco collegato ( array.h) e gli array associativi come tabelle hash. I valori al loro interno vengono nuovamente memorizzati come stringhe. La scelta di un elenco collegato per le matrici può sembrare strana, ma poiché le matrici possono essere sparse e gli indici possono essere numeri arbitrari indipendentemente dal numero di elementi contenuti nell'array, tale scelta di progettazione è un po 'più semplice da comprendere.

Tuttavia, il codice contiene anche una definizione per non utilizzatounion _value , con campi per numeri interi, numeri in virgola mobile e valori di stringa. È contrassegnato in un commento come "per il futuro", quindi è possibile che alcune versioni future di Bash memorizzino diversi tipi di scalari nelle loro forme native.


1

Per la mia vita non riesco a trovarlo da nessuna parte in così tante parole, ma è così che lo capisco.

Bash è un interprete, non un compilatore e rappresenta tutte le variabili come stringhe. Da qui tutto lo sforzo e l'enfasi che accompagna le espansioni di vario genere.

Bash passa passa tutte le variabili chiamate a declarecome stringhe con gli attributi che controllano come quella variabile deve essere ampliata per declareil magazzinaggio.

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 naturalmente

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

La coda di ciò è che anche se declareha una rappresentazione interna che cambia con i flag di attributo, le stringhe sono tutto ciò che bash vede o vuole vedere.



0

È irrilevante.

L'unico modo per interagire con le variabili di Bash è tramite Bash, quindi è impossibile per te notare alcuna differenza nel modo in cui le variabili sono archiviate in memoria, perché non puoi mai accedervi direttamente attraverso la memoria , devi sempre chiedere a Bash il loro valore e Bash possono poi tradurli in qualsiasi modo che vuole guardare come se fossero stati conservati in modo specifico.

Infatti, essi non possono neppure essere memorizzati affatto . Non so quanto siano intelligenti le implementazioni comuni di Bash, ma è almeno possibile in casi semplici determinare se una variabile verrà utilizzata e / o se verrà modificata e ottimizzarla completamente o incorporarla.


Penso che il punto della domanda fosse la rappresentazione piuttosto che il luogo
bu5hman

2
Il punto è che non puoi conoscere la rappresentazione, perché non puoi osservarla. Quindi, è irrilevante e potrebbe cambiare senza che te ne accorga mai. È semplicemente impossibile dire quale rappresentazione Bash potrebbe scegliere. Potresti approfondire il codice sorgente di un'implementazione e verificare quale rappresentazione sceglie, ma potrebbe cambiare la rappresentazione domani nella prossima versione della patch e non ci sarebbe modo di saperlo.
Jörg W Mittag,

Variabili di Schroedingers? Concordo fondamentalmente con te sul fatto che la rappresentazione sottostante sia irrilevante (vedi la mia risposta) ma nell'usare bash stiamo effettivamente "codificando un'interfaccia" e la rappresentazione nell'interfaccia è filante.
Bu5hman,

2
Sì, ma la domanda non riguarda la rappresentazione al limite dell'interfaccia, ma in particolare il modo in cui vengono "archiviati in memoria". E a questa domanda risponderei: non possiamo, non possiamo e non dovremmo saperlo.
Jörg W Mittag,

Il che parafrasa l'ultima riga del mio post ..... come ho già detto, siamo d'accordo ...... e dato il rappresentante dei PO e la natura della domanda, penso che avranno un punteggio ragionevole per i compiti, chiunque viene citato ;-).
Bu5hman,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.