wake-up-neo.net

Lesen Sie die durch Tabulatoren getrennte Dateizeile in das Array

Ich möchte eine Datei zeilenweise in ein Skript einlesen. Jede Zeile in der Datei besteht aus mehreren Werten, die durch einen Tabulator getrennt sind. Ich möchte jede Zeile in ein Array einlesen. 

Ein typisches Bash-Beispiel "Datei nach Zeile lesen";

while read line
do
echo $line;
done < "myfile"

Für mich sieht myfile jedoch so aus (tabulatorgetrennte Werte);

value1 value2 value3
value4 value5 value6

Bei jeder Wiederholung der Schleife möchte ich, dass jede Zeile in ein Array geht, so dass ich es kann

while read line into myArray
do
 echo myArray[0]
 echo myArray[1]
 echo myArray[2]
done < "myfile"

Dies würde das Folgende in der ersten Schleifeniteration ausgeben;

value1
value2
value3

Bei der zweiten Iteration würde es dann gedruckt werden

value4
value5
value6

Ist das möglich? Die einzige Möglichkeit, die ich sehen kann, ist, eine kleine Funktion zu schreiben, um die Werte manuell herauszuziehen. Gibt es dafür eine Unterstützung in bash?

53
jwbensley

Du bist ganz in der Nähe:

while IFS=$'\t' read -r -a myArray
do
 echo "${myArray[0]}"
 echo "${myArray[1]}"
 echo "${myArray[2]}"
done < myfile

(Der -r teilt der read mit, dass \ in den Eingabedaten nicht speziell ist; der -a myArray fordert ihn auf, die Eingabezeile in Wörter aufzuteilen und die Ergebnisse in myArray zu speichern, und der IFS=$'\t' sagt dazu, dass anstelle von nur Wörter verwendet werden Der reguläre Standard von Bash erlaubt auch Leerzeichen, um Wörter zu trennen. Beachten Sie, dass dieser Ansatz einen oder mehrere Tabs als Trennzeichen behandelt. Wenn also ein Feld leer ist, werden spätere Felder in frühere Positionen in verschoben das Array. Ist das in Ordnung?)

117
ruakh

Wenn Sie wirklich jedes Wort (Bash-Bedeutung) in einen anderen Array-Index aufteilen möchten, der das Array bei jeder Durchlaufschleife durchläuft, ist die Antwort von @ ruakh der richtige Ansatz. Sie können jedoch die read-Eigenschaft verwenden, um jedes gelesene Word in verschiedene Variablen column1, column2, column3 zu zerlegen, wie in diesem Code-Snippet

while IFS=$'\t' read -r column1 column2 column3 ; do
  printf "%b\n" "column1<${column1}>"
  printf "%b\n" "column2<${column2}>"
  printf "%b\n" "column3<${column3}>"
done < "myfile"

um ein ähnliches Ergebnis zu erzielen, vermeiden Sie den Zugriff auf den Array-Index und verbessern die Lesbarkeit des Codes, indem Sie sinnvolle Variablennamen verwenden (natürlich ist columnN keine gute Idee).

7
slylittl3

Sie könnten auch versuchen,

OIFS=$IFS;
IFS="\t";

animals=`cat animals.txt`
animalArray=$animals;

for animal in $animalArray
do
    echo $animal
done

IFS=$OIFS;
0