プロパティファイル のプロパティを連想配列に読み込みます。 どうすればよいですか?
解析対象の詳細:ハッシュと等号。それ以外はすべてボーナスです。
プロパティファイルの内容の例:
# comment
a=value-a
b=http://prefix.suffix:8080/?key=value
c=password_with\\backslash-and=equals
このbash連想配列をそのファイルから構築したいのですが。
declare -A props='(
[a]="value-a"
[b]="http://prefix.suffix:8080/?key=value"
[c]="password_with\\backslash-and=equals" )'
(その連想配列でのdeclare -p
の予期される出力。${props[c]}
にはバックスラッシュが1つだけ含まれていることに注意してください。"\\"
は'\'
です)。
Perl
の- Config::Properties
モジュールのような実際のパーサーを使用してください。スクリプト全体をPerl
で実行しますが、bash
を使用する必要がある場合は、次のようにすることができます。
typeset -A props
while IFS= read -rd '' key && IFS= read -rd '' value; do
props[$key]=$value
done < <(
Perl -MConfig::Properties -l0 -e '
$p = Config::Properties->new();
$p->load(STDIN);
print for $p->properties' < file.properties
)
(zsh
でも動作します)。
bash
に完全なパーサーを実装することは、多くの作業であり、ホイールの再発明を意味します。組み込みのread
は、これらのプロパティファイルに非常に類似した入力形式を想定しているため、単純なwhile read
ループで適切なサブセットを実装できます。
typeset -A props
while IFS=$':= \t' read key value; do
[[ $key = [#!]* ]] || [[ $key = "" ]] || props[$key]=$value
done < file.properties
(ksh93
およびzsh
、連想配列をサポートする他の2つのBourneのようなシェルでも動作します)。
それは処理します:
prop = value
prop: value
prop value
!
および#
オプションの先行ブランクあり)foo\:\:bar=value
、サンプルではfoo=\ bar
またはpassword_with\\backslash-and=equals
のように)。ただし、 仕様 に対してチェックすると
\n
、\r
、\uXXXX
...シーケンスを処理しません$IFS
はIFS空白文字ではないため、\f
に追加することはできません)。foo: bar =
などの入力の場合、${props[foo]}
ではなくbar =
にbar
を格納します(ただし、foo: bar:baz:
でも問題ありません)。これは、プロパティの値に1つの(エスケープされていない)区切り文字(:
オプションでSPC/TAB文字で囲まれている、=
オプションでSPC/TAB文字で囲まれている、または1つ以上のSPC /のシーケンスが含まれている場合にのみ問題になりますTAB文字)と最後にあります。\!
または\#
で始まるコメント行として扱われます。名前が!
または#
で始まるプロパティの問題のみ。に
prop=1\
2\
3
1 2 3
の代わりに123
を取得します。継続行の先頭のスペースは、本来あるべきように無視されません。
そのデータフォーマットの最も一般的なサブセットについては、 bash変数展開 と正規表現マッチングを使用して、短い関数を使用できます。
注:これは、行が^key = value$
形式、または^#.*$
および^!.*$
(コメント)。コードを適応させるか、そうでなければデータを前処理する
$ cat /tmp/propdata
k1 = v1
# A comment
k2 = v2and some s=t=u=f=f
! Another comment
k3 = v3
$ unset DATA
$ declare -A DATA
$ props(){ while read line || [[ -n $line ]]; do
[[ "$line" =~ ^#|^! ]] && continue;
if [[ "${line% =*}" ]]; then DATA[${line% =*}]="${line#*= }" ; fi ;
done < $1 ; }
$ props /tmp/propdata
$ echo "${DATA[k3]}"
v3
$ echo "${DATA[k2]}"
v2and some s=t=u=f=f
編集:キーと値の「=」の前後のスペースを削除するように更新されました
Edit2:コメントもフィルタリングします。
declare -A properties
function readPopertyFile
{
while read line || [[ -n $line ]]; do
key=`echo $line | cut -s -d'=' -f1`
if [ -n "$key" ]; then
value=`echo $line | cut -d'=' -f2-`
properties["$key"]="$value"
fi
done < $1
}
使用法:
readPopertyFile "file.properties"
プロパティをproperties
という名前の連想配列変数に読み込みます。
* bashで動作します。他のシェルについては知らない。
*複数行のプロパティを処理しません。
これがBash4 +のハウツーです
#!/usr/bin/env bash
declare -A properties
# Read with:
# IFS (Field Separator) =
# -d (Record separator) newline
# first field before separator as k (key)
# second field after separator and reminder of record as v (value)
while IFS='=' read -d $'\n' -r k v; do
# Skip lines starting with sharp
# or lines containing only space or empty lines
[[ "$k" =~ ^([[:space:]]*|[[:space:]]*#.*)$ ]] && continue
# Store key value into assoc array
properties[$k]="$v"
# stdin the properties file
done < file.properties
# display the array for testing
typeset -p properties
file.properties
:
# comment
a=value-a
b=http://prefix.suffix:8080/?key=value
c=password_with\\backslash-and=equals
d e=the d e value
# comment
提供されたデータサンプルからのこのスクリプトの出力:
declare -A properties=(["d e"]="the d e value" [c]="password_with\\\\backslash-and=equals" [b]="http://prefix.suffix:8080/?key=value" [a]="value-a" )