2012-02-13 6 views
1

Je suis un débutant à Bourne shell et je veux faire une simple simulation de tableau. Cela fonctionne:Comment passer une variable shell à awk dans Bourne shell?

COLORS='FF0000 0000FF 00FF00' 
i=2 
color=$(echo ${COLORS} | awk '{print $2}') 
echo "color selected: $color" 

Ce que je veux faire est de passer $i au lieu du paramètre $2 fixe en version imprimée (ce sera ensuite utilisé dans une boucle). J'ai passé des heures à trouver la bonne combinaison de guillemets simples et doubles pour le faire, pas de chance.

Le plus proche je suis arrivé est

color=$("echo ${COLORS} | awk '{print "$"${i}}'") 

Le résultat de l'exécution est:

+ COLORS=FF0000 0000FF 00FF00 
+ i=2 
+ echo FF0000 0000FF 00FF00 | awk '{print $2}' 
./tempgraph.sh: ./tempgraph.sh: 37: echo FF0000 0000FF 00FF00 | awk '{print $2}': not found 
+ color= 
+ echo color selected: 
color selected: 

Toute aide est appréciée.

Répondre

1

Je ferais comme ça:

color=$(echo ${COLORS} | awk "{print \$$i}") 

Si vous utilisez '...', le contenu n'est pas dépliée. Mais vous voulez que la valeur de $i soit insérée dans votre script. Donc, "..." doit être utilisé, ce qui fait l'expansion variable. Mais vous voulez également un $ devant le numéro pour AWK, donc vous devez lui échapper (\$).

+0

Merci! Cela fonctionne bien, même si je ne suis pas sûr de mieux comprendre les citations. On pourrait penser que les guillemets sont mangés par la coquille après l'expansion des choses, mais il semble qu'ils sont également passés à awk. – Arthur

+0

Ils sont * mangés par le shell, mais les guillemets simples le sont aussi. Les deux entourent une chaîne. Par exemple, habituellement 'foo a b' passe' a' comme premier argument de 'foo', et' b' comme deuxième argument. Mais avec 'foo" a b "' le shell passe 'a b' comme unique argument de' foo'. La grande différence entre les guillemets simples et doubles est qu'avec les guillemets doubles, vous pouvez "incorporer" d'autres choses, comme des variables: si vous passez "$ i" comme argument, la chaîne "$ i" est effectivement passée. Mais avec '" $ i "', le contenu de la variable 'i' est passé. – DarkDust

5

Ne perdez pas votre temps à essayer d'obtenir le shell pour développer correctement la variable dans la commande awk, il suffit de définir une variable en utilisant -v:

echo $COLORS | awk -v col=2 '{ print $col }' 

En termes de votre variable i, cela devient:

i=1 
echo $COLORS | awk -v col=$i '{ print $col }' 
+0

Merci, cela fonctionne parfaitement. J'ai accepté l'autre réponse parce que cela pourrait aider d'autres personnes à se battre avec des citations coquines. – Arthur

2

Vous pouvez également obtenir votre environnement directement:

export COLORS='FF0000 0000FF 00FF00' 
awk 'END {split(ENVIRON["COLORS"],colors);for(col in colors) { print "Color",col,"is",colors[col]}}' /dev/null 

qui donne la sortie suivante sur ce mac:

Color 2 is 0000FF 
Color 3 is 00FF00 
Color 1 is FF0000 
+1

Vous pouvez également obtenir 'i' de la même manière, soit par' export i', soit en appelant awk avec 'i = 1 awk ...'. –

+0

Exactement. Cela permet d'éviter le problème de citation et vous permet de saisir un nombre arbitraire de valeurs hors de votre environnement. Voici ce qui est génial avec Unix ™: Nous avons plusieurs façons d'obtenir les informations pertinentes dans le programme. –

1

variables attribuées sur invokation comme -v foo=bar sont disponibles dans le BEGIN où variable affectée avec un baz=qux simples ne sont pas.

BEGIN { print foo, bar; } 
{ print foo, bar; } 

voir la différence:

echo Don\'t Panic! | awk -f ./hello.awk -v foo=Hello bar=World 
Hello 
Hello World