bash - script - sed substitution




passer les paramètres du shell à awk ne fonctionne pas (3)

Pourquoi ça marche

for myfile in `find . -name "R*VER" -mtime +1`
do
   SHELLVAR=`grep ^err $myfile || echo "No error"`
   ECHO $SHELLVAR
done

et sorties

No error
err ->BIST Login Fail 3922 err 
No error
err ->IR Remote Key 1 3310 err 

Mais cela ne

for myfile in `find . -name "R*VER" -mtime +1`
do
   SHELLVAR=`grep ^err $myfile || echo "No error"`
   awk -v awkvar=${SHELLVAR} '{print awkvar}'
done

et sorties

awk: cmd. line:1: fatal: cannot open file `{print awkvar}' for reading (No such file or directory)

Qu'est-ce que je rate?


Vous devez $SHELLVAR , pour empêcher le shell de le diviser.

awk -v awkvar="${SHELLVAR}" '{print awkvar}'

Ce que vous essayez de faire est possible mais ... un peu bizarre. Voici une alternative pour vous:

for f in $(find . -name "R*VER" -mtime +1)
do
    echo "$f"
    awk 'BEGIN{ec=0} /^err/{ec+=1;print} END{if(ec==0){print "No error"}}' "$f"
done

De cette façon, vous n'avez pas à vous soucier de grep , vous n'avez pas à vous soucier des variables shell et pouvez garder votre logique au même endroit dans une seule langue.

Notez que ce code n'est que partiellement testé car je n'ai pas vos fichiers de données, mais les tests que j'ai effectués ont bien fonctionné.

Si vous voulez, vous pouvez même faire un pas de plus et écrire le tout dans awk . C'est, après tout, un langage de programmation complet et polyvalent (avec, IMO, une syntaxe beaucoup plus propre que bash ). De cette façon, vous évitez le besoin de find , grep et bash entièrement. Cependant, je n'écrirai pas ce script. Vous devrez aller chercher la page de manuel d' awk et lire vous-même les fichiers d'E / S.


Est-ce que $SHELLVAR contient un espace? Si c'est le cas, votre script awk est mal interprété, et le {print awkvar} est supposé être un nom de fichier et pas le programme AWK réel.

Vous avez également un problème où votre boucle for et le programme awk sont tous les deux en train d'aspirer STDIN. En fait, votre boucle for ne sera exécutée qu'une seule fois puisque l'AWK lira dans tous les STDIN jusqu'à ce qu'il se termine. À la fin, vous obtiendrez la même ligne encore et encore, et votre programme cessera de fonctionner pendant que l' awk attend plus de STDIN.

Je pense que tu veux faire quelque chose comme ça ...

find . -name "R*VER" -mtime +1 | while read myfile
do
    echo "$SHELLVAR" | awk '{print $0}'
done

De cette façon, votre commande echo alimente votre awk, ce qui empêchera awk de lire l'instruction find.

En aparté, vous feriez mieux de faire ceci:

find . -name "R*VER" -mtime +1 | while read myfile
do
   ...
done

Plutôt que ceci:

for myfile in `find . -name "R*VER" -mtime +1`
do
   ...
done

C'est pour plusieurs raisons:

  1. Le tampon de ligne de commande peut déborder, et vous perdrez les noms de fichiers, mais vous ne verrez jamais d'erreur.

  2. La commande find du second exemple doit d'abord se terminer avant que la boucle for puisse commencer à s'exécuter. Dans le premier exemple, la recherche est alimentée dans la boucle while.

ADDENDA

Maintenant que j'ai vu la réponse de just-my-correct-opinion , je me rends compte de ce que vous avez vraiment fait de mal: Vous avez oublié le nom du fichier dans la commande awk :

find . -name "R*VER" -mtime +1 | while read myfile
do
   SHELLVAR=`grep ^err $myfile || echo "No error"`
   awk -v awkvar=${SHELLVAR} '{print awkvar}' $myfile
done

Maintenant, la question est de savoir ce que vous faites exactement avec l' awk . Vous $SHELVAR rien sauf la valeur de $SHELVAR pour chaque ligne du fichier. Ce n'est probablement pas ce que vous voulez faire. En fait, pourquoi ne pas simplement faire ceci:

find . -name "R*VER" -mtime +1 | while read myfile
do
   SHELLVAR=$(grep -q "^err" $myfile")
   if [ "x$SHELLVAR" != "x" ]
   then
      echo "$SHELLVAR"
   fi
done

De cette façon, vous imprimez $SHELLVAR , mais seulement si $SHELLVAR est vide.

Ou, vous pouvez utiliser awk pour imprimer uniquement les lignes correspondant à votre regex:

find . -name "R*VER" -mtime +1 | while read myfile
do
   awk '/^err/ {print $0}' $myfile
done




awk