2010-12-13 114 views
1

J'ai un petit script qui lit simplement chaque ligne d'un fichier, récupère le champ id, lance l'utilitaire pour obtenir le nom et ajoute le nom à la fin. Le problème est le fichier d'entrée est énorme (2 Go). Comme la sortie est la même que l'entrée avec un nom de char 10-30 ajouté, il est du même ordre de grandeur. Comment puis-je l'optimiser pour lire des tampons volumineux, traiter dans des tampons, puis écrire des tampons dans le fichier afin de minimiser le nombre d'accès aux fichiers?Optimisation de script ksh

#!/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 

Merci

Répondre

1

Vous pouvez accélérer les choses considérablement en éliminant les deux appels à cut à chaque itération de la boucle. Il peut également être plus rapide de déplacer la redirection vers votre fichier de sortie à la fin de la boucle. Puisque vous ne vous présentez pas un exemple d'une ligne d'entrée, ou ce id2name comprend (il est possible que c'est un goulot d'étranglement) ou ce que sa production ressemble, je ne peux offrir cette approximation:

#!/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}" 

Le système d'exploitation fera le tampon pour vous.

Edit:

Si votre version de ksh n'a pas <<<, essayez ceci:

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

(. Si vous utilisez Bash, cela ne fonctionnerait pas)

+0

Merci Dennis. id2name obtient le nom d'utilisateur en fonction de l'identifiant et je n'ai aucun contrôle sur l'utilitaire. Cependant, je veux avoir les identifiants et les noms correspondants et faire une recherche locale avant de frapper la DB. J'ai essayé de composer -A, mais il n'est pas reconnu sous ksh. Malheureusement sur SunOS, ksh93 n'est pas disponible. Y a-t-il une solution alternative? Merci – Kiran

+0

Hmm, obtenir l'erreur de syntaxe pour la ligne: IFS =: lire -r champ1 champ2 champ3 NOM reste <<< $ (id2name $ id) erreur de syntaxe à la ligne 9: <<'inattendu Est-il << au lieu de <<< ou mon interpréteur est-il une mauvaise version? – Kiran

+0

@Kiran: Voir mes réponses modifiées. –