Come leggere diverse righe di un file in diverse variabili?


14

Vorrei leggere diverse righe di un file di testo in diverse variabili. Per esempio

input.txt:

line1 foo foobar bar
line2 bar
line3 foo
line4 foobar bar

Voglio questo risultato a essere memorizzato in variabili var1, var2, var3e var4in modo tale che

var1=line1 foo foobar bar
var2=line2 bar

e così via.

Qualcuno potrebbe dirmi come è fatto. Ho provato a usare evalin un ciclo for. Non sembra funzionare.



3
Questo è un cattivo approccio. Dal momento che in pratica l'unico motivo per le variabili set è quello di fare qualcosa con loro, e dato che ci sono un gran numero di strumenti specificamente progettati per fare le cose con ogni riga di testo in un file (Awk, Sed, grep, cut, et. Al.), è molto meglio fare quello che devi fare. Non micromanage in uno script di shell; orchestrare strumenti per portare a termine il lavoro.
Wildcard il

Risposte:


20

Faresti:

unset -v line1 line2
{ IFS= read -r line1 && IFS= read -r line2; } < input.txt

O:

{ line1=$(line) && line2=$(line); } < input.txt

(meno efficiente in quanto lineraramente integrato e la maggior parte delle shell ha bisogno di fork per implementare la sostituzione dei comandi. lineInoltre non è più un comando standard).

Per utilizzare un ciclo:

unset -v line1 line2 line3
for var in line1 line2 line3; do
  IFS= read -r "$var" || break
done < input.txt

Oppure per definire automaticamente i nomi delle variabili come line<++n>:

n=1; while IFS= read -r "line$n"; do
  n=$((n + 1))
done < input.txt

Nota che bashsupporta le variabili di array e un readarraybuiltin per leggere le righe in un array:

readarray -t line < input.txt

Nota comunque che contrariamente alla maggior parte delle altre shell, gli bashindici di array iniziano da 0 non 1 (ereditato da ksh), quindi la prima riga sarà inserita${line[0]} , non ${line[1]}(anche se come ha mostrato @Costas , puoi fare in modo che readarray(aka mapfile) inizi a scrivere i valori in indice 1 (le bashmatrici sono anche contrarie alla maggior parte degli altri gusci che sono matrici sparse ) con -O 1).

Vedi anche: Capire "IFS = read -r line"?


12

Offrirò di usare l'array per tali compiti

mapfile -t -O 1 var <input.txt

in modo da avere in ogni riga ${var[1]}, ${var[2]}e così via


Questo one-liner funziona molto bene. Risolto il problema per me.
Matt Zabojnik,

0

Questo non è esattamente quello che hai chiesto, ma potrebbe funzionare per le tue esigenze. È possibile serializzare i dati con Awk. Nota che questo si interromperà se $ 1 non è un nome di variabile valido:

awk '
function quote(str,   d, m, x, y, z) {
  d = "\47"; m = split(str, x, d)
  for (y in x) z = z d x[y] (y < m ? d "\\" d : d)
  return z
}
{
  print $1 "=" quote($0)
}
' input.txt > /tmp/input.sh
. /tmp/input.sh

Risultato:

$ echo "$line1"
line1 foo foobar bar

Questo è un codice davvero strano! Sembra che tu stia usando awk per trasformare l'intero file di input in uno script bash che poi procedi. Ho una vaga idea di cosa stia facendo quote (). Nomi di variabili più descrittivi sarebbero d'aiuto. Potresti spiegare le cose un po 'di più?
Joe,
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.