web-dev-qa-db-fra.com

Lire une ligne de fichier séparée par des tabulations dans un tableau

Je voudrais lire un fichier dans un script, ligne par ligne. Chaque ligne du fichier contient plusieurs valeurs séparées par un onglet. J'aimerais lire chaque ligne dans un tableau. 

Exemple typique "lire fichier par ligne" de bash;

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

Pour moi cependant, mon fichier ressemble à ceci (valeurs séparées par des tabulations);

value1 value2 value3
value4 value5 value6

A chaque itération de la boucle, j'aimerais que chaque ligne soit dans un tableau afin que je puisse

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

Ceci afficherait ce qui suit sur la première itération de la boucle.

value1
value2
value3

Ensuite, à la deuxième itération, elle serait imprimée.

value4
value5
value6

Est-ce possible? Le seul moyen que je vois est d'écrire une petite fonction pour décomposer les valeurs manuellement, existe-t-il un support intégré dans bash pour cela?

53
jwbensley

Vous êtes très proche:

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

(Le -r indique à read que \ n'est pas spécial dans les données d'entrée; le -a myArray lui dit de fractionner la ligne d'entrée en mots et de stocker les résultats dans myArray; et le IFS=$'\t' lui dit de n'utiliser que des tabulations pour séparer les mots, au lieu du défaut par défaut de Bash, qui permet également aux espaces de séparer les mots également. Cette approche traitera un ou more onglets en tant que délimiteur, donc si un champ est vide, les champs suivants seront "décalés" vers des positions antérieures dans le tableau. Est-ce correct?)

125
ruakh

Si vous voulez vraiment scinder chaque mot (signification bash) en un index de tableau différent, en modifiant complètement le tableau à chaque itération de la boucle while, la réponse de @ ruakh est la bonne approche. Mais vous pouvez utiliser la propriété read pour diviser chaque mot lu en différentes variables column1, column2, column3 comme dans cet extrait de code.

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"

atteindre un résultat similaire en évitant d’accéder aux index des tableaux et en améliorant la lisibilité de votre code en utilisant des noms de variable significatifs (bien sûr, utiliser columnN n’est pas une bonne idée de le faire).

7
slylittl3

Tu pourrais aussi essayer,

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

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

for animal in $animalArray
do
    echo $animal
done

IFS=$OIFS;
0
Dinuksha Samanage