2009-11-05 12 views
24

Mam na myśli użycie sed do odczytu pliku .properties, ale zastanawiałem się, czy istnieje lepszy sposób na zrobienie tego ze skryptu Bash?Czytanie pliku java .properties z bash

+0

który jest wspaniałym pytanie :) W tym konkretnym Chciałem zobaczyć, czy istnieje prosty sposób, którego mi brakuje (nie wiem o \ zbyt głupim, aby myśleć o itp.) –

+0

Spróbuj użyć Gradle do zbudowania i wdrożenia, a nie BASH – dart

Odpowiedz

14

Wymienione wyżej rozwiązania będą działały na podstawach. Myślę jednak, że nie obejmują one wartości wielowierszowych. Oto program awk, który będzie analizować właściwości Javy ze standardowego wejścia i wytwarzają zmienne środowiskowe, na standardowe wyjście:

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"; 
} 

Jak widać, wartości obsługujący kilka linii uczynić to bardziej skomplikowane. Aby zobaczyć wartości właściwości w skorupkach, tylko źródło na wyjściu: „”

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

Zmienne będą miały „_” w miejscu, więc some.property nieruchomość będzie some_property w skorupkach.

Jeśli masz pliki właściwości ANT, które mają interpolację właściwości (np. "$ {Foo.bar}"), to zalecamy użycie Groovy z AntBuilder. Jest to my wiki page on this very topic.

+0

Poprawiłem błąd w skrypcie, gdy wartość wielowierszowa jest ostatnią definicją i kończy się pustą linią – Toote

1

W Perl:

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

nie testowano, i powinien być bardziej tolerancyjne wiodącym/spacje, komentarze itd, ale masz pomysł. To czy korzystasz z Perla (lub innego języka) ponad sed jest naprawdę zależne od tego, co chcesz zrobić z właściwościami po ich sparsowaniu z pliku.

Zwróć uwagę, że (jak zaznaczono w komentarzach) pliki właściwości Java mogą mieć multiple forms of delimiters (chociaż nie widziałem niczego używanego w praktyce poza dwukropkami). Dlatego podział wykorzystuje wybór postaci do podziału.

Ostatecznie, może być lepiej wyłączyć za pomocą modułu Config::Properties w Perl, który jest zbudowany, aby rozwiązać ten problem.

+0

To niekoniecznie musi działać. Klucze i wartości pliku właściwości można podzielić spacjami, znakiem = lub znakiem: (mogą być również inne sposoby). Sądzę, że możesz także mieszać i dopasowywać używane ograniczniki w jednym pliku właściwości. –

+0

@Thomas - zauważyć. Chociaż w praktyce nie przypominam sobie, by widziałem coś innego niż dwukropki. –

0

Mam niektóre shell scripts, które muszą wyszukać niektóre właściwości i użyć ich jako argumentów dla programów, których nie napisałem. Sercem skryptu jest linia tak:

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

Skutecznie, to grep na klucz i odfiltrować rzeczy przed dwukropkiem i po każdym hash.

1

Jeśli chcesz użyć sed do analizowania pliku -Wszelkie- .properties, może skończyć się z dość skomplikowane rozwiązanie, ponieważ format pozwala podziały wiersza, nie notowanych ciągi, Unicode, itp: http://en.wikipedia.org/wiki/.properties

jeden możliwy Obejście spowodowałoby użycie samego java do wstępnego przetworzenia pliku .properties w coś przyjaznego dla bashu, a następnie wygenerowania go. Np .:

plik .properties:

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

zostanie przekształcony:

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

oczywiście, że przyniesie gorsze osiągi, ale wdrożenie byłoby prostsze/jaśniejszy.

+1

'line_b = $ 'Linia \ nZ \ nBreaks!' ' –

+0

Dennis, to nie działa jakoś: http://pastebin.com/m503047e8. Czy czegoś brakuje? – PaoloVictor

4

Jedną z opcji jest napisanie prostego programu Java, aby zrobić to za Ciebie - następnie uruchom program Java w swoim skrypcie. To może wydawać się głupie, jeśli czytasz właściwości tylko z jednego pliku właściwości. Jednak staje się to bardzo przydatne, gdy próbujesz uzyskać wartość konfiguracji z konfiguracji podobnej do Commons Commons: CompositeConfiguration wspieranej przez pliki właściwości. Przez pewien czas udawało nam się wdrożyć to, czego potrzebowaliśmy w naszych skryptach powłoki, aby uzyskać to samo zachowanie, które otrzymywaliśmy od CompositeConfiguration. Potem rozwialiśmy się i zdaliśmy sobie sprawę, że powinniśmy po prostu pozwolić, aby praca nam została wykonana! Nie oczekuję, że będzie to popularna odpowiedź, ale mam nadzieję, że okaże się przydatna.

0

jeśli chcesz użyć "powłoki", najlepszym narzędziem do parsowania plików i odpowiedniej kontroli programowania jest (g) awk. Użyj tylko sed podstawiania.

0

Czasami przesyłam plik właściwości do skryptu bash. Spowoduje to ustawienie w skrypcie zmiennych środowiskowych z nazwami i zawartością z pliku. Może to też wystarczy dla ciebie. Jeśli musisz zrobić "prawdziwą" analizę, oczywiście nie jest to droga do zrobienia.

0

Hmm, właśnie dzisiaj napotkam ten sam problem. Jest to rozwiązanie biedaka, co prawda bardziej prosta niż mądry;)

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

wtedy, właściwość „my.java.prop” mogą być dostępne jako $ my_java_prop.

Można to zrobić za pomocą sed lub cokolwiek innego, ale w końcu poszedłem z rubinem na jego "irb", który był przydatny do eksperymentowania. Jest dość ograniczony (kropki powinny być zastąpione tylko przed "=", bez obsługi komentarzy), ale może być punktem wyjścia.

@Daniel, Próbowałem go pobrać, ale Bash nie lubił kropek w nazwach zmiennych.

8

Napisałem scenariusz, aby rozwiązać problem i umieścić go na moim githubie.

Zobacz properties-parser

+1

Awesome! Skopiowałem skrypt do mojego projektu i ładnie odczytałem właściwości. – Will

0

miałem pewne sukcesy z

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

To będzie prawdopodobnie najprostszy sposób: grep + wyciąć

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

To jest to, co lubię najbardziej w prostych przypadkach. Ale poprawiłbym to za pomocą 'grep"^$ PROP_KEY = "' (łącznie z ogranicznikami^i =), ponieważ klucze właściwości są często prefiksami lub przyrostkami innych kluczy. – Deleplace

+3

To się nie powiedzie w przypadku każdej własności zawierającej znak równości. Lepszym (bardziej kompletnym, krótszym, a nawet nieco szybszym) rozwiązaniem byłoby "sed"/^ $ 2 = /!re; s /// "" $ 1 "', który ma taką samą logikę jak powyższy 'grep', ale także usuwa dopasowaną część, pozostawiając tylko wartość parametru do wydrukowania. –

+0

Właściwości pozwalają na odstępy między nazwą właściwości a znakiem równości. Używanie wyrażenia regularnego '^ $ 2 * =' z grep lub sed pozwala na spacje – ataylor