web-dev-qa-db-fra.com

bash + lire les variables et les valeurs du fichier par le script bash

J'ai la variable de fichier et les valeurs suivantes

# more file.txt
export worker01="sdg sdh sdi sdj sdk"
export worker02="sdg sdh sdi sdj sdm"
export worker03="sdg sdh sdi sdj sdf"

J'exécute la source afin de lire la variable

# source file.txt

exemple:

echo $worker01
sdg sdh sdi sdj sdk

jusqu'à présent, tout est parfait

mais maintenant je veux lire les variables du fichier et imprimer les valeurs par simple boucle bash je vais lire le deuxième champ et essayer d'imprimer la valeur de la variable

#  for i in ` sed s'/=/ /g'  /tmp/file.txt | awk '{print $2}' `
   do  
   echo $i
   declare var="$i"
   echo $var
   done

mais son impression uniquement la variable et non les valeurs

worker01
worker01
worker02
worker02
worker03
worker03

production attendue:

worker01
sdg sdh sdi sdj sdk
worker02
sdg sdh sdi sdj sdm
worker03
sdg sdh sdi sdj sdf
6
yael

Vous avez export worker01="sdg sdh sdi sdj sdk", puis vous remplacez = avec un espace pour obtenir export worker01 "sdg sdh sdi sdj sdk". Les champs séparés par des espaces qui sont export, worker01, "sdg, sdh, etc.

Il vaut probablement mieux se séparer sur =, et supprimez les guillemets, donc avec juste le Shell:

$ while IFS== read -r key val ; do
    val=${val%\"}; val=${val#\"}; key=${key#export };
    echo "$key = $val";
  done < vars
worker01 = sdg sdh sdi sdj sdk
worker02 = sdg sdh sdi sdj sdm
worker03 = sdg sdh sdi sdj sdf

key contient le nom de la variable, val la valeur. Bien sûr, cela n'analyse pas réellement l'entrée, il supprime simplement les guillemets doubles s'ils se trouvent là.

5
ilkkachu

Avec awk seul:

awk -F'"' '{print $2}' file.txt
# To print the variable name as well:
awk '{gsub(/[:=]/," "); gsub(/[:"]/,""); if ($1 = "export") {$1=""; print $0}}' file.txt

pour le boucler, vous pouvez:

for i in "$(awk -F\" '{print $2}' file.txt)"; do
    var="$i"
    echo "$var"
done
my_array=($(awk -F\" '{print $2}' file.txt))
for element in "${my_var[@]}"; do
    another_var="$element"
    echo "$another_var"
done

Si vous souhaitez également imprimer le nom de la variable dans votre boucle, vous pouvez le faire:

#! /usr/bin/env bash -
while read -r line; do
    if [[ "$(awk '{print $1}' <<<"$line")" == 'export' ]]; then
        var_name="$(awk '{print $2}' <<<"$line" | awk -F'=' '{print $1}')"
        var_value="$(awk -F\" '{print $2}' <<<"$line")"
        echo -e "${var_name}\n${var_value}"
    else
        continue
    fi
done<file.txt

Production:

$ ./script.sh
worker01
sdg sdh sdi sdj sdk
worker02
sdg sdh sdi sdj sdm
worker03
sdg sdh sdi sdj sdf
3
jesse_b

Tout d'abord, vous pouvez obtenir les noms des variables avec cette commande GNU grep, en utilisant une expression régulière compatible Perl:

grep -oP 'export \K[^=]+' file.txt

Ensuite, vous pouvez lire la sortie de cela dans un tableau bash avec:

mapfile -t variables < <(grep -oP 'export \K[^=]+' file.txt)

Cela utilise la commande bash intégrée mapfile et une substitution de processus .

Enfin, parcourez les noms des variables et utilisez expansion de paramètre indirect pour obtenir les valeurs:

for v in "${variables[@]}"; do 
    printf "varname=%s\tvalue=%s\n" "$v" "${!v}"
done
varname=worker01        value=sdg sdh sdi sdj sdk
varname=worker02        value=sdg sdh sdi sdj sdm
varname=worker03        value=sdg sdh sdi sdj sdf
2
glenn jackman

Vous pouvez utiliser ce sed

sed -E 's/[^ ]* ([^=]*)="([^"]*)"/\1\n\2/' file.txt

Ou cet awk

awk -F '"|=' '{split($1,a," ");print a[2]"\n"$3}' file.txt
0
ctac_