2015-03-03 8 views
22

Sto cercando di leggere un file di proprietà da uno script di shell che contiene un periodo personaggio come di seguito (.):Come leggere un file .properties che contiene le chiavi che hanno un carattere punto utilizzando Shell script di

# 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 

Ho cercato di analizzare il file dopo aver acquisito il file ma non funziona poiché le chiavi contengono "." carattere e ci sono anche spazi in quel valore. il file

Miei annunci risiede sempre nella stessa directory dello script o da qualche parte in/usr/share/doc

risposta

20

Poiché le variabili di shell (Bourne) non possono contenere punti, è possibile sostituirle con caratteri di sottolineatura. Leggi ogni riga, traduci. nella chiave per _ e valutare.

#/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 
+0

È possibile salvare l'utente db_uat_user in una variabile e quindi passare la variabile per recuperarne il valore. Qualcosa come prima var_key = db_uat_user e poi echo "user id =" $ {"$ var_key"} comunque intern il valore var_key è db_uat_user è possibile ottenere qualcosa di simile. –

+0

@AdarshHDDev che fa domande diverse è scoraggiato su SO. Per quanto riguarda la tua domanda, è stato chiesto e risposto molte volte, ad esempio: http://unix.stackexchange.com/questions/68035/foo-and-zsh – fork2execve

6

Dal momento che i nomi delle variabili nella shell bash non può contenere un punto o spazio è meglio utilizzare un array associativo in BASH in questo modo:

#!/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 

Testing:

Usa dichiarare -p per mostrare il risultato:

> declare -p arr 

     declare -A arr='([db.uat.passwd]="secret" [db.uat.user]="saple user")' 
0

@ fork2x

ho provato come questa recensione prego e mi aggiorna se è l'approccio giusto o no.

#/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 
+0

Mi piace @ La risposta di Nicolai migliore – bakoyaro

30

Io uso semplice grep funzione all'interno di script bash per ricevere oggetti di .properties file.

Questo file di proprietà viene utilizzato in due punti: per configurare l'ambiente di sviluppo e come parametri dell'applicazione.

credo che grep può funzionare lento in grandi cicli ma risolve le mie esigenze quando voglio preparare dev ambiente.

Spero che qualcuno lo troverà utile.

Esempio:

file: 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 

file: 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 
+4

Mi piace in questo modo. Un miglioramento per il tuo grep: ora corrisponde alla stringa in qualsiasi punto della linea. Puoi usare 'grep '^ \\\ s * $ {1} =" env/$ {ENV} .properties | cut -d' = '-f2' per abbinare chiavi intere all'inizio della riga (esclusi spazi bianchi opzionali). – jhyot

+0

@jhyot, grazie, hai ragione. Inoltre questo metodo ha dei limiti, ad esempio non consente di fare riferimento ad altre proprietà @ app.v1 = test - $ {app.v2} @. Risolve il mio bisogno per ora, ma credo che dovrò migliorarlo molto presto. – Nicolai

+0

Ottimo approccio! Penso che lo adotterò nel mio lavoro. – bakoyaro

1

Ho trovato utilizzando while IFS='=' read -r per essere un po 'lento (non so perché, forse qualcuno potrebbe spiegare brevemente in un commento o indicare una risposta SO?). Ho anche trovato la risposta di @Nicolai molto semplice come one-liner, ma molto inefficiente in quanto eseguirà la scansione dell'intero file di proprietà più e più volte per ogni singola chiamata di prop.

Ho trovato una soluzione che risponde alla domanda, si comporta bene ed è un one-liner (linea bit verbose).

La soluzione fa di sourcing, ma i massaggi il contenuto prima di 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 

Spiegazione:

grep -v '^ *#': eliminare righe di commento grep '[^ ] *=': scarta righe senza = split($0,a,"="): la linea si divide in = e negozi in array a, ovvero [1] è la chiave, a [2] è il valore gensub(/\./, "_", "g", a[1]): sostituisce . con _ print gensub... "=" a[2]} concatena il risultato di gensub sopra con = e valore.

+0

Il tuo codice mi dà l'errore '/ dev/fd/63: riga 1: utente: comando non trovato' usando'./app.properties' con i contenuti come dati in questione. – TomRoche

+0

Suppongo che ciò sia dovuto al fatto che non si gestisce lo spazio nel primo "valore" del file = 'utente di esempio'. – TomRoche

Problemi correlati