Moin,
der Vollständigkeit halber hier noch 2 Varianten mit bash-Arrays. Ich musste für die 2. (flexible) Version etwas basteln, deshalb die Verspätung ;-)
1. Version: Die Feld(Variablen)-Namen sind bekannt und festgelegt. Ich nutze fest definierte bash-Arrays, die maximale Anzahl von Werten ermittle ich gleich in der 1. Schleife, um mir extra Berechnungen zu ersparen. Das Script sollte relativ einfach zu verstehen sein:
Code:
jan@jack:~/tmp/kv2csv> cat kv2csv.sh
#! /bin/bash
declare -a Artikelname1
declare -a Quantity1
declare -a Price1
max=0
while read k v; do
case $k in
Artikelname1)
n=${#Artikelname1[*]}
Artikelname1[$n]="$v"
;;
Quantity1)
n=${#Quantity1[*]}
Quantity1[$n]="$v"
;;
Price1)
n=${#Price1[*]}
Price1[$n]="$v"
;;
esac
test $max -lt $n && max=$n
done <datei
echo "Artikelname1;Quantity1;Price1"
for i in `seq 0 $max`; do
echo "${Artikelname1[$i]};${Quantity1[$i]};${Price1[$i]}"
done
exit 0
Die 2. Version ist ziemlich schwer verdaulich, zeigt aber, wie man auch in der bash mit variablen Variablennamen arbeiten kann ;-) Das wichtigste Shell-Builtin für solche Anwendungen ist eval, das einen übergebenen Ausdruck evaluiert (in der Shell ausführt). Den zu evaluierenden Ausdruck setze ich mit diversen echo-Kommandos zusammen:
Code:
jan@jack:~/tmp/kv2csv> cat kv2csv_var.sh
#! /bin/bash
max=0
vars=" "
while read k v; do
echo "$vars" | grep -q " $k " || vars="$vars$k "
m=`eval echo \`echo '${#'$k'[*]}'\``
test $max -lt $m && max=$m
eval `echo \`echo $k'['$m']='"$v"\``
done <datei
echo "$vars"
echo $vars | sed 's/ /;/g'
for i in `seq 0 $max`; do
out=""
for k in $vars; do
v="`eval echo \`echo '${'$k'['$i']}'\``"
if test -n "$out"; then
out="$out;$v"
else
out="$v"
fi
done
echo "$out"
done
exit 0
Das Ding ist sogar kürzer als die 1. Version, aber flexibel bei Anzahl und Namen der Variablen - man muss nur ziemlich lange grübeln, bis man hinter die Funktion kommt ;-) Um die Funktionsweise zu verstehen, solltet Ihr ein "set -x" an den Anfang des Scripts setzen, dann wird Euch jeder Schritt angezeigt.
Man kann noch ein wenig vereinfachen und Prozesse sparen, wenn man die Möglichkeiten der bash ausreizt (der grep könnte u. U. durch ${parameter/pattern/string} ersetzt werden, die for-Schleife im Old-Unix-Style durch die C-Style-Variante, ...).
Jan
EDIT: Die 2. Variante habe ich unnötig kompliziert gemacht (so kommt das, wenn man bastelt und bastelt und die Leichen drin lässt). So sieht es viel einleuchtender aus:
Code:
jan@jack:~/tmp/kv2csv> cat kv2csv_var.sh
#! /bin/bash
max=0
vars=" "
while read k v; do
echo "$vars" | grep -q " $k " || vars="$vars$k "
m=`eval echo '${#'$k'[*]}'`
test $max -lt $m && max=$m
eval $k'['$m']='"$v"
done <datei
echo $vars | sed 's/ /;/g'
for i in `seq 0 $max`; do
out=""
for k in $vars; do
v="`eval echo '${'$k'['$i']}'`"
test -n "$out" && out="$out;"
out="$out$v"
done
echo "$out"
done
exit 0
Lesezeichen