J'essaie de lire un fichier de propriétés à partir d'un script Shell qui contient un caractère point (.) Comme ci-dessous:
# app.properties
db.uat.user=saple user
db.uat.passwd=secret
#/bin/sh
function pause(){
read -p "$*"
}
file="./app.properties"
if [ -f "$file" ]
then
echo "$file found."
. $file
echo "User Id " $db.uat.user
echo "user password =" $db.uat.passwd
else
echo "$file not found."
fi
J'ai essayé d'analyser le fichier après l'avoir recherché, mais cela ne fonctionne pas, car les clés contiennent le "." caractère et il y a des espaces dans cette valeur aussi.
Mon fichier de propriétés réside toujours dans le même répertoire du script ou quelque part dans/usr/share/doc
Comme les variables Shell (Bourne) ne peuvent pas contenir de points, vous pouvez les remplacer par des traits de soulignement. Lisez chaque ligne, traduisez. dans la clé pour _ et évaluer.
#/bin/sh
file="./app.properties"
if [ -f "$file" ]
then
echo "$file found."
while IFS='=' read -r key value
do
key=$(echo $key | tr '.' '_')
eval ${key}=\${value}
done < "$file"
echo "User Id = " ${db_uat_user}
echo "user password = " ${db_uat_passwd}
else
echo "$file not found."
fi
Notez que ce qui précède ne traduit que. Pour _, si vous avez un format plus complexe, vous pouvez utiliser des traductions supplémentaires. J'ai récemment dû analyser un fichier de propriétés Ant complet avec beaucoup de caractères désagréables, et je devais utiliser:
key=$(echo $key | tr .-/ _ | tr -cd 'A-Za-z0-9_')
J'utilise une simple fonction grep
dans le script bash pour recevoir les propriétés de .properties
fichier.
Ce fichier de propriétés que j'utilise à deux endroits - pour configurer l'environnement dev et comme paramètres d'application.
Je crois que grep
peut fonctionner lentement dans les grandes boucles, mais cela résout mes besoins lorsque je veux préparer l'environnement dev
.
J'espère que quelqu'un trouvera cela utile.
Exemple:
Fichier: setup.sh
#!/bin/bash
ENV=${1:-dev}
function prop {
grep "${1}" env/${ENV}.properties|cut -d'=' -f2
}
docker create \
--name=myapp-storage \
-p $(prop 'app.storage.address'):$(prop 'app.storage.port'):9000 \
-h $(prop 'app.storage.Host') \
-e STORAGE_ACCESS_KEY="$(prop 'app.storage.access-key')" \
-e STORAGE_SECRET_KEY="$(prop 'app.storage.secret-key')" \
-e STORAGE_BUCKET="$(prop 'app.storage.bucket')" \
-v "$(prop 'app.data-path')/storage":/app/storage \
myapp-storage:latest
docker create \
--name=myapp-database \
-p "$(prop 'app.database.address')":"$(prop 'app.database.port')":5432 \
-h "$(prop 'app.database.Host')" \
-e POSTGRES_USER="$(prop 'app.database.user')" \
-e POSTGRES_PASSWORD="$(prop 'app.database.pass')" \
-e POSTGRES_DB="$(prop 'app.database.main')" \
-e PGDATA="/app/database" \
-v "$(prop 'app.data-path')/database":/app/database \
postgres:9.5
Fichier: env/dev.properties
app.data-path=/apps/myapp/
#==========================================================
# Server properties
#==========================================================
app.server.address=127.0.0.70
app.server.Host=dev.myapp.com
app.server.port=8080
#==========================================================
# Backend properties
#==========================================================
app.backend.address=127.0.0.70
app.backend.Host=dev.myapp.com
app.backend.port=8081
app.backend.maximum.threads=5
#==========================================================
# Database properties
#==========================================================
app.database.address=127.0.0.70
app.database.Host=database.myapp.com
app.database.port=5432
app.database.user=dev-user-name
app.database.pass=dev-password
app.database.main=dev-database
#==========================================================
# Storage properties
#==========================================================
app.storage.address=127.0.0.70
app.storage.Host=storage.myapp.com
app.storage.port=4569
app.storage.endpoint=http://storage.myapp.com:4569
app.storage.access-key=dev-access-key
app.storage.secret-key=dev-secret-key
app.storage.region=us-east-1
app.storage.bucket=dev-bucket
Usage:
./setup.sh dev
Comme les noms de variables dans le shell BASH ne peuvent pas contenir de point ou d'espace, il est préférable d'utiliser un tableau associatif dans BASH comme ceci:
#!/bin/bash
# declare an associative array
declare -A arr
# read file line by line and populate the array. Field separator is "="
while IFS='=' read -r k v; do
arr["$k"]="$v"
done < app.properties
Test:
Utilisez declare -p pour afficher le résultat:
> declare -p arr
declare -A arr='([db.uat.passwd]="secret" [db.uat.user]="saple user" )'
J’ai trouvé que l’utilisation de while IFS='=' read -r
Était un peu lente (je ne sais pas pourquoi, peut-être que quelqu'un pourrait expliquer brièvement dans un commentaire ou indiquer un SO réponse?). @Nicolai a trouvé une réponse très soignée en une ligne, mais très inefficace, car elle analysera tout le fichier de propriétés à chaque fois pour chaque appel de prop
.
J'ai trouvé une solution qui répond à la question, fonctionne bien et c'est un one-liner (bit verbose line).
La solution effectue le sourcing mais masse le contenu avant le sourcing:
#!/usr/bin/env bash
source <(grep -v '^ *#' ./app.properties | grep '[^ ] *=' | awk '{split($0,a,"="); print gensub(/\./, "_", "g", a[1]) "=" a[2]}')
echo $db_uat_user
Explication:
grep -v '^ *#'
: Ignore les lignes de commentaires grep '[^ ] *='
: Supprime les lignes sans =
split($0,a,"=")
: divise la ligne à =
Et la stocke dans le tableau a
, ie un [1] est la clé, un [2] est la valeur gensub(/\./, "_", "g", a[1])
: remplace .
par _
print gensub... "=" a[2]}
concatène le résultat de gensub
ci-dessus avec =
et de la valeur.
Edit: Comme d'autres l'ont souligné, il existe des problèmes d'incompatibilités (awk) et ne valide pas le contenu pour voir si chaque ligne du fichier de propriétés est en réalité une paire kv. Mais le but ici est de montrer l’idée générale d’une solution à la fois rapide et propre. Le sourcing semble être la solution, car il charge les propriétés une fois pouvant être utilisées plusieurs fois.
@ fork2x
J'ai essayé comme ça. S'il vous plaît examiner et me mettre à jour si c'est la bonne approche ou non.
#/bin/sh
function pause(){
read -p "$*"
}
file="./apptest.properties"
if [ -f "$file" ]
then
echo "$file found."
dbUser=`sed '/^\#/d' $file | grep 'db.uat.user' | tail -n 1 | cut -d "=" -f2- | sed 's/^[[:space:]]*//;s/[[:space:]]*$//'`
dbPass=`sed '/^\#/d' $file | grep 'db.uat.passwd' | tail -n 1 | cut -d "=" -f2- | sed 's/^[[:space:]]*//;s/[[:space:]]*$//'`
echo database user = $dbUser
echo database pass = $dbPass
else
echo "$file not found."
fi