Bashスクリプトの途中に次のような文字列配列があると想像してみましょう。
example1.log
example1.log.1
log2.log
xpto.log
xpto.log.1
xpto.log.2
次の形式の文字列を含む連想配列(必要な配列構造の表現)に変換する方法はありますか?
{
"example1" : [ "example1.log", "example1.log.1" ],
"log2" : [ "log2.log" ],
"xpto" : [ "xpto.log", "xpto.log.1", "xpto.log.2" ]
}
メモ:
- 初期文字列は常に
non-predictable-name
++.log
と似た形式を持ちます.x
(オプションの点と整数)。
ありがとうございます。
答え1
解決策は次のとおりですbash
(バージョン> = 4)。
declare -A logs
for logfile in *; do
logs[${logfile%%.*}]+="$logfile "
done
連想配列を使用する例として、次のように印刷できます。
for log in "${!logs[@]}"; do
echo "$log:"
for file in ${logs[$log]}; do
echo "- $file"
done
done
(ログファイル名にスペースがないとします)
答え2
bash
連想配列は欠点にもかかわらず の配列からインスピレーションを得ましたが、ksh93
その値にスカラー以外の項目を割り当てることはサポートしていません。
値が配列になる可能性がある連想配列には、次のものが必要ですksh93
。
$ ksh -c 'typeset -A logs; for f in *.log*; do logs[${f%.log*}]+=($f); done; typeset -p logs'
typeset -A logs=([example1]=(example1.log example1.log.1) [log2]=(log2.log) [xpto]=(xpto.log xpto.log.1 xpto.log.2) )
これを繰り返すには、次のようにします。
typeset -A logs
for f in *.log*; do logs[${f%.log*}]+=($f); done
for key in "${!logs[@]}"; do
printf '%s:\n' "$key"
for file in "${logs[$key][@]}"; do
printf ' File: "%s"\n' "$file"
done
done
zsh
連想配列はスカラー値のみを持つことができますが、これらの値には NUL 文字を含めることができるため、任意のファイル名のリストを NUL 文字で区切って保存できます。を使用してくださいbash
。ファイル名はすべて現在のディレクトリにあるので、区切ります/
。または、ファイル名に特定の文字がないと仮定できる場合は、これを使用できます(たとえば、@xhienneの空白文字アプローチ)。また、bash
連想配列にはキーがnullにすることができないという制限があります。
答え3
cat - <<\eof |
example1.log
example1.log.1
log2.log
xpto.log
xpto.log.1
xpto.log.2
eof
perl -lne '
/(.*)\.log(?=\.\d+$|$)/ and
push(@{$h{$1}}, qq/"$_"/), $h[-1+keys %h]=$1;
END{
print for
q/{/,
join(",\n",
map {
join($",
qq/\t"$_"/,
q/:/,
q/[/,
join(", ", @{$h{$_}}),
q/]/,
)
} @h
),
q/}/
}
'
出力
{
"example1" : [ "example1.log", "example1.log.1" ],
"log2" : [ "log2.log" ],
"xpto" : [ "xpto.log", "xpto.log.1", "xpto.log.2" ]
}