2010-12-13 7 views
1

Ich habe ein kleines Skript, das liest einfach jede Zeile einer Datei, ruft ID-Feld, führt Dienstprogramm, um den Namen zu erhalten und hängt den Namen am Ende. Das Problem ist, dass die Eingabedatei riesig ist (2 GB). Da die Ausgabe dieselbe ist wie die Eingabe mit einem angehängten 10-30 Char-Namen, liegt sie in der gleichen Größenordnung. Wie kann ich es optimieren, um große Puffer zu lesen, in Puffern zu verarbeiten und dann Puffer in die Datei zu schreiben, so dass die Anzahl der Dateizugriffe minimiert wird?ksh script optimization

#!/bin/ksh 
while read line 
do 
    id=`echo ${line}|cut -d',' -f 3` 

    NAME=$(id2name ${id} | cut -d':' -f 4) 

    if [[ $? -ne 0 ]]; then 
     NAME="ERROR" 
     echo "Error getting name from id2name for id: ${id}" 
    fi 

    echo "${line},\"${NAME}\"" >> ${MYFILE} 
done < ${MYFILE}.csv 

Dank

Antwort

1

können Sie die Dinge beschleunigen, indem die Beseitigung der beiden Anrufe zu cut in jeder Iteration der Schleife erheblich. Es kann auch schneller sein, die Umleitung in die Ausgabedatei an das Ende der Schleife zu verschieben. Da Sie nicht über ein Beispiel einer Eingangsleitung zeigen oder welche id2name besteht aus (es ist möglich, es zu einem Engpass ist) oder, was seine Ausgabe aussieht, kann ich nur diese Annäherung bieten:

#!/bin/ksh 
while IFS=, read -r field1 field2 id remainder # use appropriate var names 
do 
    line=$field1,$field2,$id,$remainder 
    # warning - reused variables 
    IFS=: read -r field1 field2 field3 NAME remainder <<< $(id2name "$id") 
    if [[ $? -ne 0 ]]; then 
     NAME="ERROR" 
     # if you want this message to go to stderr instead of being included in the output file include the >&2 as I've done here 
     echo "Error getting name from id2name for id: ${id}" >&2 
    fi 
    echo "${line},\"${NAME}\"" 
done < "${MYFILE}.csv" > "${MYFILE}" 

Das OS wird tun das Puffern für dich.

Edit:

Wenn Ihre Version von KSH nicht <<< hat, versuchen Sie dies:

id2name "$id" | IFS=: read -r field1 field2 field3 NAME remainder 

(. Wenn Sie Bash verwendet wurden, würde dies nicht funktionieren)

+0

Danke Dennis. id2name erhält den Benutzernamen basierend auf der ID und ich habe keine Kontrolle über das Dienstprogramm. Allerdings möchte ich die IDs und die entsprechenden Namen haben und lokal nachschlagen, bevor ich auf die db stoße. Ich habe versucht, setzen Sie -A, aber es ist nicht unter ksh erkannt. Auf SunOS ist ksh93 leider nicht verfügbar. Gibt es eine alternative Lösung? Danke – Kiran

+0

Hmm, erhalten Syntaxfehler für die Zeile: IFS =: lesen -r Feld1 Feld2 Feld3 NAME Rest <<< $ (ID2Name $ ID) Syntaxfehler bei Zeile 9: '<'unerwartet Ist es << statt <<< oder ist mein Dolmetscher schlechte Version? – Kiran

+0

@Kiran: Siehe meine bearbeitete Antwort. –