2009-11-05 14 views
24

Sto pensando di usare sed per leggere il file .properties, ma mi chiedevo se c'è un modo più intelligente di farlo con lo script di bash?Leggere il file java .properties da bash

+0

Questo è un meraviglioso domanda :) In questo specifico Volevo vedere se c'è un modo semplice che mi manca (non so su cosa sia troppo stupido da pensare ecc.) –

+0

Prova ad usare Gradle per costruire e distribuire, non BASH – dart

risposta

14

Le soluzioni sopra menzionate funzioneranno per le basi. Non penso che coprano i valori multi-linea però. Ecco un programma di awk che analizzare le proprietà Java da standard input e produrre le variabili di ambiente di shell per stdout:

BEGIN { 
    FS="="; 
    print "# BEGIN"; 
    n=""; 
    v=""; 
    c=0; # Not a line continuation. 
} 
/^\#/ { # The line is a comment. Breaks line continuation. 
    c=0; 
    next; 
} 
/\\$/ && (c==0) && (NF>=2) { # Name value pair with a line continuation... 
    e=index($0,"="); 
    n=substr($0,1,e-1); 
    v=substr($0,e+1,length($0) - e - 1); # Trim off the backslash. 
    c=1;         # Line continuation mode. 
    next; 
} 
/^[^\\]+\\$/ && (c==1) { # Line continuation. Accumulate the value. 
    v= "" v substr($0,1,length($0)-1); 
    next; 
} 
((c==1) || (NF>=2)) && !/^[^\\]+\\$/ { # End of line continuation, or a single line name/value pair 
    if (c==0) { # Single line name/value pair 
     e=index($0,"="); 
     n=substr($0,1,e-1); 
     v=substr($0,e+1,length($0) - e); 
    } else { # Line continuation mode - last line of the value. 
     c=0; # Turn off line continuation mode. 
     v= "" v $0; 
    } 
    # Make sure the name is a legal shell variable name 
    gsub(/[^A-Za-z0-9_]/,"_",n); 
    # Remove newlines from the value. 
    gsub(/[\n\r]/,"",v); 
    print n "=\"" v "\""; 
    n = ""; 
    v = ""; 
} 
END { 
    print "# END"; 
} 

Come si può vedere, i valori multilinea rendere le cose più complesse. Per visualizzare i valori delle proprietà in guscio, proprio sorgente nell'output: ''

cat myproperties.properties | awk -f readproperties.awk > temp.sh 
source temp.sh 

Le variabili avranno '_' al posto di, in modo che il some.property proprietà sarà some_property in guscio.

Se si dispone di file di proprietà ANT con interpolazione delle proprietà (ad esempio "$ {foo.bar}"), si consiglia di utilizzare Groovy con AntBuilder.

Qui è my wiki page on this very topic.

+0

Ho corretto un bug con lo script quando un valore multi-linea è l'ultimo definito e termina con una riga vuota – Toote

1

In Perl:

while(<STDIN>) { 
    ($prop,$val)=split(/[=: ]/, $_, 2); 
    # and do stuff for each prop/val 
} 

Non testato, e dovrebbe essere più tollerante di condurre/gli spazi finali, commenti ecc, ma si ottiene l'idea. Sia che tu usi Perl (o un'altra lingua) su sed dipende in realtà da cosa vuoi fare con le proprietà una volta che le hai estratte dal file.

Si noti che (come evidenziato nei commenti) i file delle proprietà Java possono avere multiple forms of delimiters (anche se non ho visto nulla di usato in pratica diverso dai due punti). Quindi la divisione usa una scelta di personaggi su cui dividersi.

In definitiva, potrebbe essere meglio utilizzare il modulo Config::Properties in Perl, che è stato creato per risolvere questo problema specifico.

+0

Ciò non funzionerà necessariamente. Le chiavi e i valori del file delle proprietà possono essere delimitati da spazi, il carattere = o dal carattere: (potrebbero esserci anche altri modi). Credo che puoi anche mescolare e abbinare i delimitatori che usi in un singolo file di proprietà. –

+0

@Thomas - notato. Anche se in pratica non ricordo di aver visto altro che i due punti utilizzati. –

0

Ho alcuni shell scripts che hanno bisogno di cercare alcuni .properties e li usano come argomenti per programmi che non ho scritto. Il cuore dello script è una linea come questa:

dbUrlFile=$(grep database.url.file etc/zocalo.conf | sed -e "s/.*: //" -e "s/#.*//") 

In effetti, questo è grep per la chiave e filtrare la roba prima dei due punti e dopo ogni hash.

1

Se si desidera utilizzare sed per analizzare il file .properties -Any-, si può finire con una soluzione piuttosto complessa, dal momento che il formato consente interruzioni di riga, stringhe non quotati, unicode, ecc: http://en.wikipedia.org/wiki/.properties

una possibile la soluzione alternativa sarebbe utilizzare java per preelaborare il file .properties in qualcosa di bash-friendly, quindi eseguirlo. Es .:

.properties di file:

line_a : "ABC" 
line_b = Line\ 
     With\ 
     Breaks! 
line_c = I'm unquoted :(

sarebbero trasformati in:

line_a="ABC" 
line_b=`echo -e "Line\nWith\nBreaks!"` 
line_c="I'm unquoted :(" 

Naturalmente, che avrebbe ceduto performance peggiore, ma l'implementazione sarebbe più semplice/più chiaro.

+1

'line_b = $ 'Line \ nWith \ nBreaks!'' –

+0

Dennis, non ha funzionato in qualche modo: http://pastebin.com/m503047e8. Mi sto perdendo qualcosa? – PaoloVictor

4

Un'opzione è scrivere un semplice programma Java per farlo per voi, quindi eseguire il programma Java nello script. Potrebbe sembrare sciocco se stai leggendo le proprietà da un singolo file di proprietà. Tuttavia, diventa molto utile quando stai cercando di ottenere un valore di configurazione da qualcosa come una Configurazione Commons CompositeConfiguration supportata dai file delle proprietà. Per un certo periodo, abbiamo intrapreso il percorso per implementare ciò che ci serviva nei nostri script di shell per ottenere lo stesso comportamento che ottenevamo da CompositeConfiguration. Poi ci siamo resi conto che dovevamo semplicemente lasciare che lo CompositeConfiguration facesse il lavoro per noi! Non mi aspetto che questa sia una risposta popolare, ma spero che la trovi utile.

0

se si desidera utilizzare "shell", lo strumento migliore per analizzare i file e avere il controllo di programmazione corretto è (g) awk. Usa sed solo sostituzione semplice.

0

A volte ho appena acquistato il file delle proprietà nello script di bash. Questo porterà a variabili di ambiente impostate nello script con i nomi e il contenuto del file. Forse è abbastanza per te. Se devi fare un "vero" parsing, questa non è la strada da percorrere, ovviamente.

0

Hmm, ho appena incontrato lo stesso problema oggi. Questa è la soluzione povero, certamente più semplice di intelligente;)

decl=`ruby -ne 'puts chomp.sub(/=(.*)/,%q{="\1";}).gsub(".","_")' my.properties` 
eval $decl 

poi, una proprietà 'my.java.prop' possibile accedere da $ my_java_prop.

Questo può essere fatto con sed o qualsiasi altra cosa, ma alla fine sono andato con rubino per il suo 'irb' che è stato utile per la sperimentazione. È abbastanza limitato (i punti devono essere sostituiti solo prima di "=", nessuna gestione dei commenti), ma potrebbe essere un punto di partenza.

@Daniel, ho provato a cercarlo, ma a Bash non piacevano i punti nei nomi delle variabili.

8

Ho scritto una sceneggiatura per risolvere il problema e inserirla nel mio github.

Vedi properties-parser

+1

Impressionante! Copiato lo script nel mio progetto e ben letto nelle proprietà. – Will

0

ho avuto un certo successo con

PROPERTIES_FILE=project.properties 
function source_property { 
    local name=$1 
    eval "$name=\"$(sed -n '/^'"$name"'=/,/^[A-Z]\+_*[A-Z]*=/p' $PROPERTIES_FILE|sed -e 's/^'"$name"'=//g' -e 's/"/\\"/g'|head -n -1)\"" 
} 

    source_property 'SOME_PROPERTY' 
24

Questo sarebbe probabilmente il modo più semplice: grep + tagliare

# Usage: get_property FILE KEY 
function get_property 
{ 
    grep "^$2=" "$1" | cut -d'=' -f2 
} 
+0

Questo è quello che mi piace di più per i casi semplici. Ma vorrei modificare con 'grep"^$ PROP_KEY = "' (compresi i^e = delimitatori) perché le chiavi di proprietà sono frequentemente prefisso o postfisso di altre chiavi. – Deleplace

+3

Ciò non riuscirà su alcuna proprietà che contiene un segno di uguale. Una soluzione migliore (più completa, più breve e anche leggermente più veloce) sarebbe "sed"/^ $ 2 = /!d; s /// "" $ 1 "' che ha la stessa logica di 'grep' precedente ma elimina anche la parte corrispondente, lasciando solo il valore del parametro da stampare –

+0

Le proprietà consentono lo spazio tra il nome della proprietà e il segno di uguale. Usando l'espressione regolare '^ $ 2 * =' con grep o sed consente gli spazi. – ataylor

Problemi correlati