À l'aide de bash pour la variable de boucle dans awk impression
J'essaie de comprendre une situation spécifique à l'intérieur de bash, awk:
Je veux utiliser le awk opérateur binaire pour de concaténation de chaîne entre les deux variables (un espace) comme la variable d'itération,$i
, dans un bash pour la boucle:
$ for i in ' '; do
echo "foo bar" | awk '{print $1$i$2}'
done
foofoo barbar
Sortie attendue est: foobar
Question 1
- Ce qui se passe? RÉPONSE (marqué comme correcte)
Question 2
- Comment puis-je obtenir awk pour utiliser la concaténation de chaîne comme ci-dessus bash pour la boucle? RÉPONSE
De référence
$ $SHELL --version | head -n1
GNU bash, version 4.3.42(4)-release (x86_64-unknown-cygwin)
$ awk --version | head -n1
GNU Awk 4.1.3, API: 1.1 (GNU MPFR 3.1.3, GNU MP 6.1.0)
Test complet
$ for i in '+' '-' '*' '/' '%' ' ' ''; do echo "2.0 4.0" | awk '{print $1$i$2}'; done
2.02.0 4.04.0
2.02.0 4.04.0
2.02.0 4.04.0
2.02.0 4.04.0
2.02.0 4.04.0
2.02.0 4.04.0
2.02.0 4.04.0
Vous devez vous connecter pour publier un commentaire.
Il semble un peu difficile. En fait, il imprime
foo
,foo bar
etbar
. Comme la valeur dei
n'est pas définie dans awk (c'est un bash variable) il est considéré comme$0
(je ne sais pas ce comportement, mais il a un sens).Modifier un peu le code que
De sortie:
Si vous souhaitez passer la valeur de la variable
i
vous pouvez le faire à l'aide de-v
argument. Mais$i
ne fonctionnera pas tant que la valeur dei
doit être un nombre compris dans$i
, utilisez donc simplei
.De sortie:
-v
, mais ça ne fonctionne pas, la sortie defor i in ' '; do echo "foo bar" | awk -v i="$i" '{print $1"<"i">"$2}'; done
estfoo< >bar
, il doit effectuer la concaténation de chaîne, donc la sortie estfoo<>bar
-v
et cela ne fonctionne toujours pasfor i in ' '; do echo "foo bar" | awk -v i="$i" '{print $1"<"'i'">"$2}'; done
sortiesfoo< >bar
foo
etbar
il suffit de ne pas passer le$i
awk! Essayezawk '{print $1$2}'
. La sortie estfoobar
. (Mais je ne comprends pas l'importance de$i
alors... 😉 )I want to use the string operator to perform concatenation within a for loop:
Juste un exercice pour le plaisir sur bash/awk fondamentaux 🙂the string operator
signifie? Une concaténation dansawk
est d'écrire les deux variables sont proches les uns des autres. Pour les paramètres positionnels, il peut être fait comme$1$2
pour les variables normales, il peut être fait commei j
.foobar
puis le$i
ne devrait pas ajouter. Dans ce cas, utilisez$1$2
. Si vous souhaitez également concaténer la variable d'environnementi
ensuite, vous pouvez utiliserawk -v i="$i"
et puis$1 i$2
. Bien sûr, vous pouvez utiliser directement la variable d'environnement à l'aide de la'"$i"'
mais il est beaucoup plus difficile à lire et lesawk
script estprint $1 $2
.i
est un régulier de la variable shell, pas une variable d'environnement.$1
, ...) paramètres positionnels. Vous êtes confus Awk et concepts de shell. Aveci
pas défini, à la fois GNU Awk et Mawk, en effet, interpréter$i
comme$0
(c'est à dire, l'ensemble de l'entrée de la ligne), mais BSD/OSX Awk en fait breaks avecawk: illegal field $(), name "i"
.name=value
. Siname
arrive à être un shell valide identifiant, une variable nomméename
est créé avec la valeur donnée. Aussi, toute variable shellx
peut avoir son exportation ensemble d'attributs, ce qui signifie que la chaîne dex=$x
(après expansion) sera ajouté à l'environnement de tous les processus enfants.awk
s! À mon humble avis OSX erreur est le meilleur traitement de cette question...print
arguments avec des espaces, de manière à montrer comment Awk concaténation de chaîne fonctionne différemment de la coquille? Vous peut ne$1$2
, mais c'est sur le plan conceptuel propre à faire$1 $2
, en particulier étant donné que vous ne pouvez pas fairexy
avec le terrain, les variablesx
ety
(comme vous le décrivez):{ print $1 "<" i ">" $2 }
export
. Cependant, la coquille aussi idéalement expose préexistante variables d'environnement (par exemple,$PATH
). Ainsi, "non exportée variable d'environnement" est une contradiction dans les termes.$i
une variable d'environnement est tout simplement incorrect (et le qualifiant de "non exportés" n'aide pas).it is a non exported bash environment variable
n'a pas de sens puisque le termeenvironment variable
ne s'applique pas (i
à l'extérieur de awk est simplement une variable du shell et$i
dans awk est la tentative d'accès au champ dont le numéro est stocké dans la variable awki
) et le comportement dans le script awk serait la même si la variable d'environnementi
a été exporté ou non. Votre formulation est trompeuse, car, au moins, il semble que l'exportation de la variable d'environnementi
ferait une différence.J'ai essayé de faire un commentaire, mais il ya tout simplement trop de choses à dire et qu'il a besoin de formatage:
@adam vous semblez avoir une certaine incompréhension fondamentale de awk c'est ce qui rend difficile pour vous de comprendre ce que vous êtes d'être dit. Je suppose qu'il revient à ceci - awk n'est pas shell. Awk est complètement distincte de l'outil/de la langue avec sa propre champ d'application, les variables, les fonctions, etc.
N'essayez PAS d'accéder à la valeur de variables shell directement dans un script awk en utilisant intermédiaire entre guillemets simples (par exemple,
awk '{print $1'"$i"'$2}'
) parce que cela va tourner à la valeur de la variable d'environnement dans le cadre de la awk code avant de l'interprète, il lit et vous ouvrir à d'horribles erreurs avec cryptique des messages d'erreur (ou pire encore, insidieuse bugs avec pas de messages d'erreur) compte tenu des diverses valeurs de$i
.Vous dites que vous
Cannot get -v to work even without for loop:
mais alors vous montrer qu'il fonctionne parfaitement deux fois:Dans le cas ci-dessus, vous créez un awk variable nommée
var
qui contient un caractère vide" "
. Ensuite, vous print $1 (foo
), suivie par la var (" "
), suivie par $2 (bar
) et la sortie est<foo>< ><bar>
exactement comme il devrait être.Dans tous vos exemples vous êtes à la définition d'une variable à un seul caractère espace, la concaténation qu'avec certains autres valeurs (par ex.
-v var=" "
puis$1var$2
) et puis pour une raison quelconque attend à ce que l'espace de caractère pour ne pas être présents dans la sortie.Dans le cas ci-dessus, vous créez un awk variable nommée
var
qui contient un caractère vide" "
. Lorsque vous écrivez un script shell (awk, sed, grep, peu importe) qui est placée entre guillemets simples:puis vous dire
cmd
à interpréter/exécuter ce qui est à l'intérieur le signe des guillemets. Vous ne peut pas inclure des guillemets simples dans un seul devis délimité par des script - c'est shell fondamentaux. Donc, lorsque vous écrivez:l'intérieur des guillemets simples sont fait sortir de la
any_cmd
de la langue et de revenir à shell pour interpréter et de l'shell tente de s'étendre avant deany_cmd
est appelé. Donc, si vous avez:alors que
any_cmd
voit réellement à interpréter, c'est:mais si vous avez quelque chose là-bas que le shell ne pouvez pas développer puis il est laissé tel est donc:
est transmis à
any_cmd
comme:Donc, pour revenir à votre exemple:
La
var
entre 1 $et 2 $sera interprété par le shell première depuis la'
s autour, il y a prise de la sortie du script awk et à l'arrière de la coquille, mais ensuite, c'est juste du texte que shell ne pouvez pas développer ce qui est au dessus est transmis à awk en tant que-est ce qui le rend:et dans un rond-point de la façon que vous avez de nouveau à votre premier script et, de nouveau, la sortie est aussi prévue.
Ci-dessus a l'air compliqué mais c'est en fait très simple:
Pour concaténer des chaînes de caractères dans awk, il suffit de mettre côte à côte.
Pour transmettre la valeur d'une variable shell, awk, utilisez
-v
, par exempleawk -v awkvar="$shellvar" 'print "foo" awkvar "bar"'
.Plutôt que d'essayer d'apprendre awk par essai et erreur, lisez le livre Effective Awk Programming, 4e Édition, par Arnold Robbins en premier et ensuite jouer avec elle.
Explore: -v
l'article, je ne m'attendais pas-v
de travail. Je viens de montrer la sortie à cause de quelqu'un d'autre en disant qu'il allait travailler. Quand vous ditesDo NOT try to access the value of shell variables directly within an awk script by using intermediate single quotes...
c'était en fait ma question! Comment puis-je augmenter la variable avant de awk interprète 🙂i
ne serait pas arbitraire, il serait restreint aux valeurs comme indiqué dans le Test l'article:'+' '-' '*' '/' '%' ' '
foo bar
. Je pense que c'est déroutant de personnes dans trompeur de penser que j'essayais de faire un général de concaténation de chaîne. C'était stupide de moi.-v
, cela peut être plus clair ce que je suis en train de faire.echo "2.0 4.0" | awk -v var="+" '{print $1var$2}'
de sortie est2.0+4.0
, sortie désirée est6
. Est-il possible à l'aide de-v var="+"
? Plus clair?2.0 var 4.0
en elle et planifiée pour s'exécuter à chaque fois quesed 's/var/+/' tst.c > tmp.c && gcc tmp.c
à l'aide de ce que l'op vous voulez, au lieu de+
. Oui vous pouvez physiquement le faire fonctionner, mais je doute si vous gagnez un prix pour la C ou la programmation shell, en le faisant!Ah, j'ai compris Question 2.
Initiale de la boucle for:
Explorer: citant
Joindre
$i
dans"
:'{print $1$i$2}'
d''{print $1"$i"$2}'
Solution: citant
Qui m'a conduit à essayer de briser awk avec
'
donc$i
peuvent être correctement évaluées:'{print $1"$i"$2}'
d''{print $1'"$i"'$2}'
Solution de Test
À l'aide de la solution à tester tous les awk opérateurs binaires et nuls:
Remarque:
''
n'est pas un opérateur binaire évidemment, et est juste une vérification.Succès!
Avertissement: comme souligné par d'autres, cette solution est pas pour le général de concaténation de chaîne. La variable shell
i
ne doit être awk des opérateurs binaires. Réglagei
à toute autre variable sera probablement causer des problèmes.Explorer:
-v
À l'aide de
-v
ne semble pas permettre l'opération binaire:De sortie:
2.0+4.0
La sortie souhaitée:
6
$
pour obtenir la valeur d'une variable. awk ne le fait pas (c'est comme le C sur ce sujet). Dans awk$
est comme un operator pour obtenir la valeur de la domaine est donné par la variable:echo a b c | awk '{print $2; x=2; print x; print $x}'
sortieb
,2
,b
awk -v var=":" '{print $1 var $2}'
$<number>
est utilisé pour faire référence à l'enregistrement en cours, délimités en fonction de la variableNS
. Évidemment, si je voulais juste une solution, je le feraisecho "foo bar" | awk -v var="" '{print $1'var'$2}'
pour obtenir la sortie commefoobar
, ou tout simplement ne pas utiliser-v
à tous. Aussi, je ne veux pas d'un séparateur tel que votre suggestion fournit,:
. Ce que j'essaie de faire de l'opérateur binaire de déclenchement via<space>
pour concaténer deux variables. Je devrais être en mesure d'itérer sur tous les opérateurs binaires, comme indiqué dans Test sect. Si vous avez une solution pour ce faire à l'aide de-v
j'aimerais entendre 🙂awk '{print $1 $2}'
foo bar
je pense que c'est la confusion de beaucoup de gens. Je veux passer par la variable de l'une quelconque des opérateurs binaires (par exemple,+
,<space>
,*
, etc) dans la commande d'impression entre les deux vars. Je l'ai résolu avec la boucle for, mais je ne pense pas que c'est possible avec-v
dans une boucle for. Merci quand même pour votre aide.