Programmation shell, évitant les files temporaires

J'écris souvent des scripts shell KSH qui suivent le même schéma:

  • (1) récupérer la sortie d'une ou plusieurs command
  • (2) le formater en utilisant grep | cut | awk | sed et l'imprimer à l'écran ou dans un file

Pour ce faire, je stocke souvent la sortie de (1) dans un file temporaire, puis effectue la mise en forme dans (2) sur ce file.

Prenez ce code par exemple:

TMPFILE=file.tmp # If tmpfile exists rm it. [ -f $TMPFILE ] && rm -f $TMPFILE for SERVICE in $(myfunc); do getInfo $SERVICE > $TMPFILE # Store raw output in the TMPFILE # I resortingeve the relevant data from the TMPFILE SERV_NAME=$(head -1 $TMPFILE | sed -e 's/ $//') SERV_HOSTNAME=$(grep HOSTNAME $TMPFILE | cut -d "=" -f2) SERV_ARGS=$(grep Arguments $TMPFILE | cut -d ":" -f2) print $SERV_NAME $SEP $SERV_HOSTNAME $SEP $SERV_ARGS rm -f $TMPFILE #rm the TMPFILE in vue of next iteration done 

Y at-il un moyen, en utilisant des tuyaux, des redirections et des trucs, pour éviter d'écrire un file sur le disque à chaque fois?

Si ça aide, j'utilise ksh Version M-11/16 / 88i

Votre code ressemble à un exemple entièrement justifié d'utilisation de files temporaires. Je restrais: s'en tenir à cette approche. La seule chose qui doit vraiment être changée est la façon dont vous créez le file temporaire. Utilisez quelque chose comme

  TMP=$(tempfile) 

ou

  TMP=$(mktemp) 

ou au less

  TMP=/tmp/myscript_$$ 

De cette façon, vous ne laisserez pas le nom facilement prédire (security) et les interférences de règles entre plusieurs instances du script s'exécutant en même time.

Vous pourriez utiliser une variable:

 info="$(getInfo $SERVICE)" SERV_NAME="$(head -1 $TMPFILE <<<"$info" | sed -e 's/ $//')" ... 

De l' man ksh :

 <<<word A short form of here document in which word becomes the contents of the here-document after any parameter expan- sion, command substitution, and arithmetic substitution occur. 

Les avantages include:

  • Permet l'exécution parallèle.
  • D'après mon expérience, cela est beaucoup plus rapide que les files temporaires. À less que vous ayez autant de données que vous finissez par échanger, les ordres de magnitude devraient être plus rapides (seulement en bloquant les tampons de caching HD, qui peuvent être aussi rapides pour les petites quantités de données).
  • D'autres process ou users ne peuvent pas gâcher vos données.

Vous avez deux options:

  1. Vous récupérez datatables une fois (dans votre exemple avec getInfo ) et les stockez dans un file comme vous le faites.

  2. Vous récupérez datatables à chaque fois et ne les stockez pas localement, c'est-à-dire que vous appelez getInfo chaque fois

Je ne vois pas le problème dans la création d'un file temporaire pour éviter le retraitement / re-récupération.

Si vous craignez de quitter le file temporaire quelque part, vous pouvez toujours utiliser trap pour être sûr de le supprimer au cas où le script serait tué / interrompu

 trap "rm -f $TMPFILE" EXIT HUP INT QUIT TERM 

et utilisez mktemp pour créer un nom de file unique pour votre file temporaire.

Au lieu de générer un file, construisez des instructions d'assignation de shell et évaluez cette sortie.

 for SERVICE in $(myfunc); do eval $(getInfo $SERVICE | sed -n -e '1/\(.*\) *$/SERV_NAME="\1"/p' \ -e '/HOSTNAME/s/^[^=]*=\([^=]*\).*/SERV_HOSTNAME="\1"/p' \ -e '/Arguments/^[^:]*:\([^:]*\).*/SERV_ARGS="\1"/p') print $SERV_NAME $SEP $SERV_HOSTNAME $SED $SERV_ARGS done 

Ou si vous voulez juste imprimer l'information:

 for SERVICE in $(myfunc); do getInfo $SERVICE | awk -vsep="$SEP" ' BEGIN{OFS=sep} NR == 1 { sub(/ *$/,""); SERV_NAME=$0 } /HOSTNAME/ { split($0, HOST, /=/; SERV_HOSTNAME=HOST[2]; } /Arguments/ { split($0, ARGS, /:/; SERV_ARGS } END { print SERV_NAME, SERV_HOSTNAME, SERV_ARGS }' done