Quando si scrivono script Bash, a volte ci si trova in situazioni in cui è necessario leggere un file riga per riga. Ad esempio, potresti avere un file di testo contenente dati che dovrebbero essere elaborati dallo script.
In questo tutorial, discuteremo come leggere un file riga per riga in Bash.
Lettura di un file riga per riga Sintassi #
La sintassi più generale per leggere un file riga per riga è la seguente:
while IFS= read -r line; do
printf '%s\n' "$line"
done < input_file
o la versione equivalente a riga singola:
while IFS= read -r line; do printf '%s\n' "$line"; done < input_file
Come funziona?
Il file di input (input_file ) è il nome del file reindirizzato al ciclo while. Il read command elabora il file riga per riga, assegnando ogni riga alla line variabile. Una volta che tutte le righe sono state elaborate, il ciclo while termina.
Per impostazione predefinita, il read Il comando interpreta la barra rovesciata come un carattere di escape e rimuove tutti gli spazi bianchi iniziali e finali, che a volte possono causare comportamenti imprevisti. Per disabilitare l'escape della barra rovesciata, stiamo invocando il comando con il -r opzione, e per disabilitare il taglio, il separatore di campo interno (IFS ) è cancellato.
Stiamo usando [printf ] invece di echo per rendere il codice più portabile ed evitare comportamenti indesiderati. Ad esempio, se la riga contiene valori come "-e", verrà trattata come un'opzione di eco.
Lettura di un file riga per riga Esempi #
Diamo un'occhiata al seguente esempio. Supponiamo di avere un file chiamato distros.txt contenente un elenco di alcune delle distribuzioni Linux più popolari e i relativi gestori di pacchetti separati da virgole (, ):
Ubuntu,apt
Debian,apt
CentOS,yum
Arch Linux,pacman
Fedora,dnf
Per leggere il file riga per riga, dovresti eseguire il seguente codice nel tuo terminale:
while IFS= read -r line; do
printf '%s\n' "$line"
done < distros.txt
Il codice legge il file per riga, assegna ogni riga a una variabile e la stampa. Fondamentalmente, vedresti lo stesso output come se dovessi visualizzare il contenuto del file usando il cat comando.
E se volessi stampare solo le distribuzioni che usano apt? Un modo sarebbe usare if istruzione e controlla se la riga contiene la sottostringa apt:
while IFS= read -r line; do
if [[ "$line" == *"apt"* ]]; then
printf '%s\n' "$line"
fi
done < distros.txt
Ubuntu,apt
Debian,apt
Quando leggi un file riga per riga, puoi anche passare più di una variabile a read comando, che dividerà la riga in campi basati su IFS . Il primo campo è assegnato alla prima variabile, il secondo alla seconda variabile e così via. Se ci sono più campi che variabili, i campi rimanenti vengono assegnati all'ultima variabile.
Nell'esempio seguente, impostiamo IFS in una virgola (, ) e passare due variabili distro e pm al read comando. Tutto dall'inizio della riga fino alla prima virgola verrà assegnato alla prima variabile (distro ), e il resto della riga verrà assegnato alla seconda variabile (pm ):
while IFS=, read -r distro pm; do
printf '%s is the package manager for %s\n' "$pm" "$distro"
done < distros.txt
apt is the package manager for Ubuntu
apt is the package manager for Debian
yum is the package manager for CentOS
pacman is the package manager for Arch Linux
dnf is the package manager for Fedora
Metodi di lettura file alternativi #
Utilizzo di una sostituzione di processo #
La sostituzione del processo è una funzionalità che consente di utilizzare l'output del comando come file:
while IFS= read -r line; do
printf '%s\n' "$line"
done < <(cat input_file )
Utilizzo di una stringa Here #
Here String è una variante del documento Here. La stringa (cat input_file ) mantiene le nuove righe:
while IFS= read -r line; do
printf '%s\n' "$line"
done <<< $(cat input_file )
Utilizzo del descrittore file #
Puoi anche fornire l'input per il ciclo usando un descrittore di file:
while IFS= read -r -u9 line; do
printf '%s\n' "$line"
done 9< input_file
Quando si lavora con i descrittori di file, utilizzare un numero compreso tra 4 e 9 per evitare conflitti con i descrittori di file interni della shell.
Conclusione #
In Bash, possiamo leggere un file riga per riga usando un ciclo while e read comando.
Se hai domande o feedback, sentiti libero di lasciare un commento.