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".txtA 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?
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.
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.
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:
, 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
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.
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.