Wie liest man verschiedene Zeilen einer Datei in verschiedene Variablen?

14

Ich möchte verschiedene Zeilen einer Textdatei zu verschiedenen Variablen lesen. Beispielsweise

input.txt:

line1 foo foobar bar
line2 bar
line3 foo
line4 foobar bar

Ich möchte dieses Ergebnis in Variablen gespeichert werden var1, var2, var3und var4so , dass

var1=line1 foo foobar bar
var2=line2 bar

und so weiter.

Könnte mir bitte jemand sagen, wie es gemacht wird. Ich habe versucht, evalin einer for-Schleife zu verwenden. Es scheint nicht zu funktionieren.

neet
quelle
3
Das ist ein schlechter Ansatz. Da im Grunde der einzige Grund zu Setvariablen, ist etwas mit ihnen zu tun, und da eine große Anzahl von Werkzeugen gibt es speziell entworfen mit jeder Textzeile , Dinge zu tun in einer Datei (Awk, Sed grep, cutet. Al.), Es ist viel viel besser, einfach das zu tun, was Sie tun müssen. Nicht in einem Shell-Skript mikromanagen. Instrumente orchestrieren, um die Arbeit zu erledigen.
Wildcard

Antworten:

20

Du würdest tun:

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

Oder:

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

(Dies lineist weniger effizient, da es nur selten eingebaut ist und die meisten Shells sich trennen müssen, um die Befehlsersetzung zu implementieren. Dies lineist auch kein Standardbefehl mehr.)

So verwenden Sie eine Schleife:

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

Oder um die Namen der Variablen automatisch wie folgt zu definieren line<++n>:

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

Beachten Sie, dass bashArray-Variablen und eine integrierte readarrayFunktion zum Einlesen von Zeilen in ein Array unterstützt werden:

readarray -t line < input.txt

Beachten Sie jedoch , dass im Gegensatz zu den meisten anderen Muscheln, bashstarten Array - Indizes bei 0 nicht 1 (geerbt von ksh), so dass die erste Zeile sein wird ${line[0]}, nicht ${line[1]}(obwohl wie @Costas gezeigt hat , können Sie machen readarray(aka mapfile) beginnen die Werte bei indice Schreiben 1 ( bashArrays auch im Gegensatz zu den meisten anderen Shells sind spärliche Arrays) mit -O 1).

Siehe auch: "IFS = read -r line" verstehen?

Stéphane Chazelas
quelle
12

Ich würde anbieten, Array für solche Aufgabe (n) zu verwenden

mapfile -t -O 1 var <input.txt

so dass Sie jede Zeile in haben ${var[1]}, ${var[2]}und so weiter

Costas
quelle
Dieser Einzeiler funktioniert sehr gut. Löste das Problem für mich.
Matt Zabojnik
0

Dies ist nicht genau das, wonach Sie gefragt haben, aber es könnte für Ihre Bedürfnisse funktionieren. Sie können die Daten mit Awk serialisieren. Beachten Sie, dass dies nicht funktioniert, wenn Ihr $ 1 kein gültiger Variablenname ist:

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

Ergebnis:

$ echo "$line1"
line1 foo foobar bar
Steven Penny
quelle
Das ist ein merkwürdiger Code! Es scheint, dass Sie awk verwenden, um die gesamte Eingabedatei in ein Bash-Skript umzuwandeln, das Sie dann als Quelle verwenden. Ich habe eine vage Vorstellung davon, was quote () tut. Beschreibendere Variablennamen würden helfen. Könnten Sie die Dinge etwas näher erläutern?
Joe