Existe-t-il un moyen d'évaluer une chaîne en tant qu'expression mathématique dans awk?
balter@spectre3:~$ echo "sin(0.3) 0.3" | awk '{print $1,sin($2)}' sin(0.3) 0.29552
Je voudrais savoir un moyen d'évaluer également la première entrée à 0,29552.
5 Réponses :
awk n'a pas de fonction eval (...)
. Cela signifie que vous ne pouvez pas effectuer de traduction de chaîne en code basée sur l'entrée après l'initialisation du programme awk. Ok, peut-être que cela pourrait être fait, mais pas sans écrire votre propre moteur d'analyse et d'évaluation dans awk.
Je recommanderais d'utiliser bc
pour cet effort, comme
[edwbuck@phoenix ~]$ echo "s(0.3)" | bc -l .29552020666133957510
++ ve pour solution. Moi aussi j'ai pensé la même chose (ajouté un commentaire avec la solution) si OP avait besoin de le faire toujours en awk
uniquement :)
Pourquoi n'y a-t-il pas de bibliothèque mathématique en ligne de commande sensée pour Linux? Ma solution actuelle est m () {python -c "import math; print ($ 1);}
. Je pourrais aussi utiliser perl. Mon ancien patron l'a vu et m'a dit que je venais de construire les mondes calculatrice la plus chère.
@abalter Je pensais que bc
était pour la calculatrice de base
et satisfaisait le besoin de "maths en ligne de commande sains"; mais, les moyens de faire des mathématiques sous Linux ne manquent pas. Je reconnais que s (..)
et c (...)
sont des manières étranges d'écrire sin
et cos code >, c'est dommage qu'ils n'aient pas opté pour
sin (...)
et cos ()
. De plus, on pourrait presque utiliser l'approche echo $ (($ expr))
de bash, sauf qu'elle ne prend pas en charge trig.
@EdwinBuck Fait intéressant, POSIX limite les noms de fonction et de variable en bc à une seule lettre. (Bien que des implémentations multi-lettres soient disponibles)
@abalter wrt Pourquoi n'y a-t-il pas de bibliothèque mathématique en ligne de commande sensée pour Linux?
- parce que ce n'est pas à quoi sert un shell. Un shell est un environnement à partir duquel appeler des outils et dispose d'un petit langage pour aider à séquencer ces appels. Il n'est pas destiné / conçu pour être un langage de programmation complet et si vous essayez de l'utiliser en tant que tel, vous manquez le point.
Vous pouvez simplement créer votre propre fonction eval qui appelle à nouveau awk pour exécuter la commande que vous voulez:
$ cat tst.awk { print eval($1), sin($2) } function eval(str, cmd,line,ret) { cmd = "awk \047BEGIN{print " str "; exit}\047" if ( (cmd | getline line) > 0 ) { ret = line } close(cmd) return ret } $ echo 'sin(0.3) 0.3' | awk -f tst.awk 0.29552 0.29552 $ echo '4*7 0.3' | awk -f tst.awk 28 0.29552 $ echo 'tolower("FOO") 0.3' | awk -f tst.awk foo 0.29552
Avec la version 4.1.2 de gawk:
echo "sin(0.3) 0.3" | awk '{split($1,a,/[()]/);f=a[1];print @f(a[2]),sin($2)}'
Cela fonctionne aussi avec tolower (FOO)
.
Bonne idée pour les appels de fonction qui acceptent des arguments numériques ou de chaîne simples (vous ne pouvez tout simplement pas l'utiliser avec 4 * 7
ou index ("abc", "b")
ou sin (0,1 + 0,2)
par exemple). btw [(] | [)]
= [()]
.
Vous pouvez essayer Perl car il a la fonction eval ().
$ echo "sin(0.3) 0.3" | perl -ne ' /(\S+)\s+(\S+)/ and print eval($1), " ", $2 ' 0.29552020666134 0.3 $
Pour l'entrée donnée,
$ echo "sin(0.3)" | perl -ne ' print eval ' 0.29552020666134 $
Voici une simple doublure!
x=100; y=5; math "sqrt($x) + $y"
Exemples d'utilisation:
math 'sqrt(25)'
Rend "2"
math 1+1
Yeilds "5"
math(){ awk "BEGIN{printf $1}"; }
Yeilds "15"
Que diriez-vous d'utiliser cet
echo "sin (0.3) 0.3" | awk '{match ($ 1, / \ (. * \) /); print sin (substr ($ 1, RSTART + 1, RLENGTH-1)), sin ($ 2)}'
:) Je sais que vous voulez le faire passer comme une expression MATH (dont je ne suis pas conscient pour le moment, en regardant les documentations), a pensé une façon amusante de jouer avec celle-ci.Eh bien, il y a la version étendue du script awk
calc3
par Kenny McCormack et Alan Linton qui flotte autour des internets, voici un lien: groups.google.com/forum / #! topic / comp.lang.awk / C4SbutsY1JA L'originalcalc3 < / code> ne supportait que les opérations de base, mais celui lié semble gérer le péché et autres.
echo "sin (0.3)" | awk -f calc3.awk
produitsin (0.3) = 0.29552
echo "sin (0.3) 0.3" | perl -ne '/ (\ S +) \ s + (\ S +) / et print eval ($ 1), "", $ 2'
fonctionneraient également.