bash – comment lire correctement un fichier d’entrée dont les valeurs sont dans un tableau

J’essaie d’écrire un script qui lit un fichier (plus d’une ligne) qui est “#” séparé et les place dans un tableau afin que je puisse correspondre à certaines valeurs.

Exemple de fichier d’entrée:

us-east#1-1#abcdefg1234Ad us-west#1-3#654kjhytgr us-east#1-4#lkjhg765 

Ce que j’essaie de faire, c’est de lire chaque ligne et de me donner le match en fonction de mon paramètre d’entrée (1 $). Je suis coincé comme juste évaluer la première ligne seulement.

Voici mon code: (pour exécuter: ./myscript.sh us-east-1-3 )

 #!/usr/local/bin/bash set -x cluster=$1 KEY=./.keyfile while IFS=# declare -a arr=($(< $KEY)); do if [[ ${arr[0]}-${arr[1]} == $1 ]]; then echo "We have a match" else echo "No match" exit 1 fi done set +x 

Je suis coincé comme juste évaluer la première ligne seulement.

Parce que dans votre bloc else , vous avez une instruction de exit , supposez que si la ligne ne correspond pas, la boucle sera terminée en raison de la exit 1 , donc une itération supplémentaire n’aura pas lieu.

Après avoir lu la première ligne, us-east-1-1 n’est pas égal à us-east-1-3 , booléen false , donc dans votre bloc else , vous avez une instruction de exit , donc une terminaison

 + cluster=us-east-1-3 + KEY=./file + IFS='#' + arr=($(< $KEY)) + declare -a arr + [[ us-east-1-1 == us-east-1-3 ]] + echo 'No match' No match + exit 1 

Vous pouvez modifier comme ci-dessous pour utiliser moins de ressources, lire ligne par ligne au lieu de lire un fichier entier dans un tableau

 [akshay@localhost tmp]$ cat t.sh #!/usr/bin/env bash set -x cluster="$1" while IFS=# read -r field1 field2 restother; do if [[ "$field1-$field2" == $1 ]]; then echo "We have a match" else echo "No match" fi done < "file" set +x 

Sortie when cluster=us-east-1-3

 [akshay@localhost tmp]$ bash t.sh us-east-1-3 + cluster=us-east-1-3 + IFS='#' + read -r field1 field2 restother + [[ us-east-1-1 == us-east-1-3 ]] + echo 'No match' No match + IFS='#' + read -r field1 field2 restother + [[ us-west-1-3 == us-east-1-3 ]] + echo 'No match' No match + IFS='#' + read -r field1 field2 restother + [[ us-east-1-4 == us-east-1-3 ]] + echo 'No match' No match + IFS='#' + read -r field1 field2 restother + set +x 

Sortie when cluster=us-west-1-3

 [akshay@localhost tmp]$ bash t.sh us-west-1-3 + cluster=us-west-1-3 + IFS='#' + read -r field1 field2 restother + [[ us-east-1-1 == us-west-1-3 ]] + echo 'No match' No match + IFS='#' + read -r field1 field2 restother + [[ us-west-1-3 == us-west-1-3 ]] + echo 'We have a match' We have a match + IFS='#' + read -r field1 field2 restother + [[ us-east-1-4 == us-west-1-3 ]] + echo 'No match' No match + IFS='#' + read -r field1 field2 restother + set +x 

Vous pouvez utiliser awk pour ce type d'object, relativement plus rapidement

Voici un exemple

 $ cat file us-east#1-1#abcdefg1234Ad us-west#1-3#654kjhytgr us-east#1-4#lkjhg765 

Sortie (lorsque cluster="us-east-1-3" )

 $ awk -F'#' -v cluster="us-east-1-3" '{ print (cluster==$1"-"$2)? "We have a match": "No match"}' file No match No match No match 

Sortie (lorsque cluster="us-west-1-3" )

 $ awk -F'#' -v cluster="us-west-1-3" '{ print (cluster==$1"-"$2)? "We have a match": "No match"}' file No match We have a match No match 

Je suis d’accord avec Akshay sur le fait que c’est un bon problème à résoudre avec awk. Cependant, si vous voulez vraiment le faire avec le shell seul, ce n’est pas difficile:

 #!/usr/bin/env bash cluster="$1" keyfile=keyfile.txt ret=0 while IFS='#' read -r one two three; do if [[ "${one}-${two}" = "$cluster" ]]; then echo "match" else echo "no match" ret=1 fi done < "$keyfile" exit $ret 

La principale différence est que cela consiste à utiliser read pour traiter un stream d’entrée qui est transmis à la boucle while, plutôt que de réévaluer l’expression $(< $keyfile) pour chaque exécution de la boucle la première ligne pour chaque course).