web-dev-qa-db-ja.com

bashからJava。propertiesファイルを読み取る

.propertiesファイルを読み取るためにsedを使用することを考えていますが、bashスクリプトからそれを行うよりスマートな方法があるかどうか疑問に思っていましたか?

27
Alex N.

上記のソリューションは、基本的に機能します。ただし、複数行の値をカバーしているとは思いません。以下は、stdinからJavaプロパティを解析し、シェル環境変数をstdoutに生成するawkプログラムです。

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

ご覧のとおり、複数行の値は物事をより複雑にします。シェルのプロパティの値を確認するには、出力をソースするだけです。

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

変数には「。」の代わりに「_」が含まれるため、シェルではプロパティsome.propertyはsome_propertyになります。

プロパティ補間を含むANTプロパティファイル(例: '$ {foo.bar}')がある場合は、AntBuilderでGroovyを使用することをお勧めします。

こちらが このトピックに関する私のwikiページ です。

16
Joshua Davis

これはおそらく最も簡単な方法です:grep + cut

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

問題を解決するためのスクリプトを作成し、それをgithubに配置しました。

properties-parser を参照してください

9
Shawn

1つのオプションは、簡単なJavaプログラムを記述してそれを実行することです。その後、スクリプトでJavaプログラムを実行します。単一のプロパティファイルからプロパティを読み取るだけです。ただし、プロパティファイルに裏打ちされたCommons Configuration CompositeConfigurationのようなものから構成値を取得しようとする場合は、非常に便利です。しばらくの間、私たちはルートをたどりました。シェルスクリプトで必要なものを実装して、CompositeConfigurationから得ていたのと同じ動作を実現します。その後、賢明にして、CompositeConfigurationに作業を任せればよいことに気付きました!これは人気のある答えになると思いますが、うまくいけば、それが役に立つと思います。

4
Matt Hurne

Perlの場合:

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

テストされていません。先頭/末尾のスペース、コメントなどに対してより耐性があるはずですが、アイデアはわかります。 sedでPerl(または別の言語)を使用するかどうかは、ファイルからプロパティを解析した後、プロパティで何をしたいかによって異なります。

(コメントで強調表示されているように)Javaプロパティファイルには 複数の形式の区切り文字)を含めることができます (ただし、実際にコロン以外のものは使用していません)。したがって、分割では、文字の選択を使用して分割します。

最終的に、この特定の問題を解決するために構築されたPerlの Config :: Properties モジュールを使用したほうがよい場合があります。

1
Brian Agnew

Sedを使用して-any- .propertiesファイルを解析する場合は、形式が改行、引用符で囲まれていない文字列、ユニコードなどを許可するため、非常に複雑なソリューションになる可能性があります。 http://en.wikipedia .org/wiki/.properties

考えられる回避策の1つは、Java自体を使用して、.propertiesファイルをbashに適したものに前処理してから、ソースを作成することです。例:

.propertiesファイル:

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

に変わります:

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

もちろん、パフォーマンスは低下しますが、実装はより単純で明確になります。

1
PaoloVictor

「シェル」を使用する場合、ファイルを解析して適切なプログラミング制御を行うための最良のツールは(g)awkです。 sedのみの単純な置換を使用します。

0
ghostdog74

プロパティファイルをbashスクリプトに取り込むこともあります。これにより、ファイルの名前と内容を使用してスクリプトに環境変数が設定されます。多分それはあなたにとっても十分です。もちろん、「実際の」解析を行う必要がある場合、これは進むべき道ではありません。

0

うーん、私は今日同じ問題に遭遇しました。これは貧乏人の解決策であり、確かに賢いよりも簡単です;)

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

次に、プロパティ 'my.Java.prop'に$ my_Java_propとしてアクセスできます。

これはsedなどで実行できますが、最終的にRubyの 'irb'を使用しました。これは、実験に便利でした。かなり制限されています(ドットは '='の前にのみ置き換える必要があります。コメント処理)が、出発点になる可能性があります。

@Daniel、私はそれを調達しようとしましたが、Bashは変数名のドットが好きではありませんでした。

0
inger

私はいくつかの Shellスクリプト を使用して、いくつかの.propertiesを検索し、それらを私が記述していないプログラムの引数として使用する必要があります。スクリプトの中心は次のような行です。

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

事実上、これはキーのgrepであり、コロンの前とハッシュの後にあるものをフィルターで除外します。

0
PanCrit

私はいくつかの成功を収めてきました

    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'
0
aizen

これは、引用符が適切に解析され、引用符が指定されていない場合はスペースで終了するソリューションです。安全です。evalは使用されません。

シェルスクリプトから変数をインポートするために、.bashrcと.zshrcでこのコードを使用します。

_# Usage: _getvar VARIABLE_NAME [sourcefile...]
# Echos the value that would be assigned to VARIABLE_NAME
_getvar() {
  local VAR="$1"
  shift
  awk -v Q="'" -v QQ='"' -v VAR="$VAR" '
    function loc(text) { return index($0, text) }
    function unquote(d) { $0 = substr($0, eq+2) d; print substr($0, 1, loc(d)-1) }
    { sub(/^[ \t]+/, ""); eq = loc("=") }
    substr($0, 1, eq-1) != VAR { next }  # assignment is not for VAR: skip
    loc("=" QQ) == eq { unquote(QQ); exit }
    loc("="  Q) == eq { unquote( Q); exit }
    { print substr($1, eq + 1); exit }
  ' "$@"
}
_

これにより、目的の変数名が保存され、引数の配列がシフトされるため、残りはファイルとしてawkに渡されます。

シェル変数を呼び出してawk内の引用符文字を参照するのは非常に難しいため、コマンドラインでそれらをawk変数として定義しています。 Qは一重引用符(アポストロフィ)文字、QQは二重引用符、VARは前に保存した最初の引数です。

さらに便利なように、2つのヘルパー関数があります。 1つ目は、現在の行の特定のテキストの場所を返し、2つ目は、引用符d(「区切り文字」)を使用して、行の最初の2つの引用符の間の内容を出力します。複数行の文字列に対する安全性として、最初のdに連結された漂遊substrがあります(以下の「警告」を参照)。

POSIXシェル構文解析のコードを作成しましたが、割り当ての周囲に空白があるかどうかだけがフォーマットと異なるようです。上記のコードにその機能を追加するには、awkの4行目のsub(/[ \t]*=[ \t]*/, "=");の前にsub(…)を追加します(注:1行目は空白です)。

4行目は、先頭の空白を取り除き、最初の等号の位置を保存します。 awkがタブとして_\t_をサポートしていることを確認してください。これは古いUNIXシステムでは保証されていません。

substr行は、等号の前のテキストをVARと比較します。それが一致しない場合、その行は別の変数を割り当てているので、それをスキップして次の行に移動します。

これで、要求された変数の割り当てが得られたことがわかったので、引用符を解明するだけです。これを行うには、_="_(6行目)または_='_(7行目)の最初の場所を検索するか、引用符なし(8行目)を検索します。これらの各行は、割り当てられた値を出力します。

警告:エスケープされた引用文字がある場合、それに切り捨てられた値を返します。これを検出することは少し重要であり、私はそれを実装しないことにしました。複数行の引用符の問題もあり、最初の改行で切り捨てられます(これが上記の「漂遊d」の目的です)。このページのほとんどのソリューションは、これらの問題に悩まされています。

0
Adam Katz