Un problème bc sur la longue expression

Je veux calculer une expression en shell. J'utilise le code suivant:

pi=$(echo "scale=10; 4*a(1)" | bc -l) i=3 d=`expr (1+c($pi*($i/10)+$pi))/2 | bc -l` 

Mais ça dit

 bad pattern: (1+c(3.1415926532*(3/10)+3.1415926532))/2 

Pourquoi?

Parce que vous utilisez expr dans votre dernière command où vous devriez probablement utiliser echo .

PS Je vous conseille d'utiliser la forme $(…) dans les deux commands bc (plutôt que `…` ).

Si vous prenez mon conseil, vous n'utiliserez pas “ ou $() – c'est un peu bête. bc est un interprète interactif, orienté vers la ligne. Il lit dans une ligne de stdin, vérifie s'il en a besoin d'un autre en fonction de l'input qui vient d'être lue, puis imprime ses résultats sur stdout ou request plus sur stdin. Comme votre shell, il refusera même de faire quoi que ce soit de plus qu'une sortie ligne-tampon même si elle est écrite sur un autre terminal qu'un terminal. Il n'y a aucun besoin d'appeler un nouveau bc pour chaque calcul – en particulier dans une substitution de command qui implique également d'appeler un tout nouveau shell et d'allouer un nouveau tube.

Le meilleur moyen est de mettre en place un co-process.

 # in a bash shell exec 8<> >( : ) 9< <( bc <&8 ) echo 'b=5;++b' >&8 read b <&9 echo "$b" 

 6 

Et le bc continuera simplement à fonctionner – toutes ces valeurs de variables que vous faites tellement de travail pour faire la navette entre les process bc éphémères, commandés par command, pourraient être plus facilement stockées de manière centralisée dans un bc central.

 echo b\*b >&8; read b <&9; echo "$b" 

 32 

Et encore mieux, depuis que j'ai appris comment faire cela l'autre jour, vous pouvez mettre le process bc sur un server socket.

 { ncat -l 9000 --allow localhost -k| bc; } <>/dev/fd/1 |:& 

Et avec un shell qui parle le langage /dev/tcp :

 { echo 'b=10;b' >&0; read b; echo "$b"; } <>/dev/tcp/localhost/9000 

 10 

Cela peut devenir un peu encombrant. J'ai écrit une petite fonction appelée bchat() pour le rendre plus facile.

 bchat(){ local IFS=\; ### separate on ; printf ${1+'%s;"\n"\n';}"$*" ### print \0 if no args set -- ### init args while read bchat && ### while read <bc "${bchat:+set}" -- "$@" "${bchat:=$*}" ### append to args do :; done 2>/dev/null ### and done } <>"$BC" >&0 ### $BC must be set 

Après avoir configuré un server socket comme indiqué ci-dessus, vous pouvez utiliser cette fonction comme:

 BC=/dev/tcp/localhost/9000 bchat b=5 x='(b--)' '"x="' ++x '"b="' --b echo "$bchat" 

 x=6;b=3 

… et encore, cet état persistera aussi longtime que le process BC …

Méfiez-vous que lorsque vous définissez l'échelle a une influence sur le calcul.

Ce script:

 bc -l << \EOF scale = 10 pi = 4 * a(1) i = 3 (1 + c(pi * (i / 10) + pi)) / 2 EOF bc -l << \EOF pi = 4 * a(1) i = 3 scale = 10 (1 + c(pi * (i / 10) + pi)) / 2 EOF bc -l << \EOF pi = 4 * a(1) i = 3 r = (1 + c(pi * (i / 10) + pi)) / 2 scale = 10 r/1 EOF bc -l << \EOF scale = 100 pi = 4 * a(1) i = 3 r = (1 + c(pi * (i / 10) + pi)) / 2 scale = 15 r/1 EOF 

les sorties:

 .2061073736 .2061073739 .2061073738 .206107373853763