Créer un tableau à partir d'un fichier texte dans Bash

un script prend une URL, la Parse pour les champs requis, et redirige sa sortie pour être enregistrée dans un fichier, fichier.txt . La sortie est sauvegardée sur une nouvelle ligne chaque fois qu'un champ a été trouvé.

"151990920 de fichier".txt
A Cat
A Dog
A Mouse 
etc... 

je veux prendre file.txt et créer un tableau à partir de lui dans un nouveau script, où chaque ligne doit être sa propre variable de chaîne dans le tableau. Jusqu'à présent j'ai essayé:

#!/bin/bash

filename=file.txt
declare -a myArray
myArray=(`cat "$filename"`)

for (( i = 0 ; i < 9 ; i++))
do
  echo "Element [$i]: ${myArray[$i]}"
done

quand j'exécute ce script, whitespace se traduit par des mots qui se séparent et au lieu de

sortie désirée

Element [0]: A Cat 
Element [1]: A Dog 
etc... 

je finis par obtenir ceci:

production réelle

Element [0]: A 
Element [1]: Cat 
Element [2]: A
Element [3]: Dog 
etc... 

Comment puis-je ajuster la boucle ci-dessous de telle sorte que la chaîne entière sur chaque ligne corresponde une à une avec chaque variable dans le tableau?

47
demandé sur codeforester 2015-06-22 22:50:11

6 réponses

utiliser la mapfile commande:

mapfile -t myArray < file.txt

l'erreur est d'utiliser for -- la façon idiomatique de boucler lignes d'un fichier est:

while IFS= read -r line; do echo ">>$line<<"; done < file.txt

Voir BashFAQ/005 pour plus de détails.

61
répondu glenn jackman 2018-04-22 00:49:49

Vous pouvez le faire aussi:

oldIFS="$IFS"
IFS=$'\n' arr=($(<file))
IFS="$oldIFS"
echo "${arr[1]}" # It will print `A Dog`.

Note:

L'expansion du nom de fichier

se produit toujours. Par exemple, s'il y a une ligne avec un * littéral, elle s'étendra à tous les fichiers du dossier courant. Alors utilisez - le SEULEMENT si votre fichier est libre de ce genre de scénario.

4
répondu Jahid 2015-12-21 14:39:32

mapfile et readarray (qui sont synonymes) sont disponibles dans la version 4 et plus de Bash. Si vous avez une ancienne version de Bash, vous pouvez utiliser une boucle pour lire le fichier dans un tableau:

arr=()
while IFS= read -r line; do
  arr+=("$line")
done < file

dans le cas où le fichier a une incomplète (nouvelle ligne manquante) dernière ligne, vous pouvez utiliser cette alternative:

arr=()
while IFS= read -r line || [[ "$line" ]]  do
  arr+=("$line")
done < file

Related:

4
répondu codeforester 2018-01-18 00:06:34

, Vous pouvez simplement lire chaque ligne du fichier et l'affecter à un tableau.

#!/bin/bash
i=0
while read line 
do
        arr[$i]="$line"
        i=$((i+1))
done < file.txt
2
répondu Prateek Joshi 2017-06-26 20:04:56

utiliser mapfile ou read -a

vérifiez toujours votre code en utilisant shellcheck . Il vous donnera souvent la bonne réponse. Dans ce cas SC2207 couvre la lecture d'un fichier qui a soit espace séparé ou newline séparé des valeurs dans un tableau.

ne faites pas ceci

array=( $(mycommand) )

Fichiers avec des valeurs séparées par des sauts de ligne

mapfile -t array < <(mycommand)

valeurs séparées par des espaces

IFS=" " read -r -a array <<< "$(mycommand)"

la page shellcheck vous expliquera pourquoi on considère qu'il s'agit d'une pratique exemplaire.

0
répondu Cameron Lowell Palmer 2017-12-14 12:42:20

Cette réponse dit d'utiliser

mapfile -t myArray < file.txt

j'ai fait un shim pour mapfile si vous voulez utiliser mapfile sur bash < 4.x pour quelque raison que ce soit. Il utilise la commande mapfile si vous êtes sur bash >= 4.x

actuellement, seules les options -d et -t fonctionnent. Mais cela devrait suffire pour cette commande ci-dessus. Je n'ai testé que les macOS. Sur macOS Sierra 10.12.6, la system bash est 3.2.57(1)-release . Donc, la cale peut venir dans maniable. Vous pouvez également simplement mettre à jour votre bash avec homebrew, construire bash vous-même, etc.

Il utilise des cette technique pour définir les variables d'une pile d'appel.

0
répondu dosentmatter 2017-12-18 01:04:05