Un script prend une URL, l’analyse pour les champs obligatoires et redirige sa sortie dans un fichier, fichier.txt. La sortie est enregistrée sur une nouvelle ligne chaque fois qu'un champ est trouvé.
A Cat
A Dog
A Mouse
etc...
Je veux prendre file.txt
et créer un tableau à partir de celui-ci dans un nouveau script, où chaque ligne devient sa propre variable chaîne dans le tableau. Jusqu'ici 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
Lorsque j'exécute ce script, les espaces blancs divisent les mots et, au lieu, deviennent
Element [0]: A Cat
Element [1]: A Dog
etc...
Je finis par avoir ceci:
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 un à un avec chaque variable du tableau?
Utilisez la commande mapfile
:
mapfile -t myArray < file.txt
L'erreur utilise for
- la manière idiomatique de parcourir en boucle les lignes d'un fichier est la suivante:
while IFS= read -r line; do echo ">>$line<<"; done < file.txt
Voir BashFAQ/005 pour plus de détails.
mapfile
et readarray
(qui sont synonymes) sont disponibles à partir de la version 4 de Bash. Si vous avez une version plus ancienne 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
Si le fichier comporte une dernière ligne incomplète (nouvelle ligne manquante), vous pouvez utiliser cette alternative:
arr=()
while IFS= read -r line || [[ "$line" ]] do
arr+=("$line")
done < file
Apparenté, relié, connexe:
Vous pouvez le faire aussi:
oldIFS="$IFS"
IFS=$'\n' arr=($(<file))
IFS="$oldIFS"
echo "${arr[1]}" # It will print `A Dog`.
Remarque:
L'expansion du nom de fichier se produit toujours. Par exemple, s'il existe une ligne avec un littéral *
, elle sera étendue à tous les fichiers du dossier en cours. Ne l'utilisez donc que si votre fichier est exempt de ce genre de scénario.
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
Vérifiez toujours votre code en utilisant shellcheck . Cela vous donnera souvent la bonne réponse. Dans ce cas, SC2207 couvre la lecture d'un fichier contenant des valeurs séparées par un espace ou une nouvelle ligne dans un tableau.
array=( $(mycommand) )
mapfile -t array < <(mycommand)
IFS=" " read -r -a array <<< "$(mycommand)"
La page shellcheck vous expliquera pourquoi cela est considéré comme 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 une raison quelconque. Il utilise la commande existante 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 sur macOS. Sur macOS Sierra 10.12.6, le système bash est 3.2.57(1)-release
. Ainsi, la cale peut être utile. Vous pouvez également simplement mettre à jour votre bash avec homebrew, construire bash vous-même, etc.
Il utilise cette technique pour définir des variables dans une pile d'appels.