No, un file non viene letto automaticamente in memoria aprendolo. Sarebbe terribilmente inefficiente. sed
, ad esempio, legge il suo input riga per riga, così come molti altri strumenti Unix. Raramente deve conservare più della linea corrente in memoria.
Con awk
è lo stesso. Legge un record alla volta, che per impostazione predefinita è una riga. Se memorizzi parti dei dati di input in variabili, questo sarà extra, ovviamente 1 .
Alcune persone hanno l'abitudine di fare cose del genere
for line in $(cat file); do ...; done
Poiché il serbatoio dovrà espandere la $(cat file)
completa sostituzione di comando prima di eseguire anche la prima iterazione del for
ciclo, questo sarà letto per intero file
nella memoria (nella memoria utilizzata dalla shell eseguendo il for
loop). Questo è un po 'sciocco e anche inelegante. Invece, si dovrebbe fare
while IFS= read -r line; do ...; done <file
Questo elaborerà file
riga per riga (ma leggi Comprensione "IFS = leggi -r riga" ).
L'elaborazione dei file riga per riga nella shell è raramente necessaria, poiché la maggior parte dei programmi di utilità sono comunque orientati alla riga (consultare Perché l'utilizzo di un loop di shell per elaborare il testo è considerato una cattiva pratica? ).
Sto lavorando in bioinformatica e durante l'elaborazione di enormi quantità di dati genomici non sarei in grado di fare molto a meno che non conservassi solo i bit di dati che erano assolutamente necessari in memoria. Ad esempio, quando ho bisogno di rimuovere i bit di dati che potrebbero essere utilizzati per identificare le persone da un set di dati da 1 terabyte contenente varianti di DNA in un file VCF (perché quel tipo di dati non può essere reso pubblico), lo faccio riga per riga elaborazione con un semplice awk
programma (ciò è possibile poiché il formato VCF è orientato alla linea). Io non leggo il file in memoria, il processo lì, e scrivere di nuovo fuori di nuovo! Se il file fosse compresso, lo farei scorrere zcat
o gzip -d -c
, che, dal momento che gzip
esegue lo streaming dei dati, non leggerebbe l'intero file in memoria.
Anche con formati di file che non sono orientati alla linea, come JSON o XML, esistono stream parser che consentono di elaborare file di grandi dimensioni senza archiviarli tutti nella RAM.
Con gli eseguibili, è leggermente più complicato poiché le librerie condivise possono essere caricate su richiesta e / o condivise tra processi (vedere Caricamento delle librerie condivise e utilizzo della RAM , ad esempio).
La memorizzazione nella cache è qualcosa che non ho menzionato qui. Questa è l'azione dell'utilizzo della RAM per contenere pezzi di dati a cui si accede frequentemente. I file più piccoli (ad esempio gli eseguibili) possono essere memorizzati nella cache dal sistema operativo nella speranza che l'utente faccia molti riferimenti ad essi. Oltre alla prima lettura del file, verranno effettuati accessi successivi alla RAM anziché al disco. La memorizzazione nella cache, come il buffering di input e output, è generalmente in gran parte trasparente per l'utente e la quantità di memoria utilizzata per memorizzare nella cache le cose può cambiare in modo dinamico a seconda della quantità di RAM allocata dalle applicazioni ecc.
1 Tecnicamente, la maggior parte dei programmi probabilmente legge un blocco dei dati di input alla volta, usando il buffering esplicito, o implicitamente attraverso il buffering che fanno le librerie I / O standard, e quindi presenta quel blocco riga per riga al codice dell'utente. È molto più efficiente leggere un multiplo della dimensione del blocco del disco rispetto ad esempio a un carattere alla volta. Questa dimensione del pezzo raramente sarà più grande di una manciata di kilobyte però.