Porque você está usando expr
no seu último comando
onde você provavelmente deveria estar usando echo
.
P.S. Eu aconselho você a usar o formulário $(…)
nos dois comandos bc
(em vez de '…'
).
Eu quero calcular uma expressão no shell. Eu uso o seguinte código:
pi=$(echo "scale=10; 4*a(1)" | bc -l)
i=3
d='expr (1+c($pi*($i/10)+$pi))/2 | bc -l'
Mas diz
bad pattern: (1+c(3.1415926532*(3/10)+3.1415926532))/2
Por quê?
Se você seguir meu conselho, não usará '' ou $()
- é um pouco bobo. bc
é um interpretador interativo e orientado a linhas. Ele lê em uma linha de stdin, verifica se precisa de outro baseado na entrada que acabou de ler e então imprime seus resultados para stdout ou solicita mais informações sobre stdin. Como o seu shell, ele até se recusará a fazer algo mais do que a saída do buffer de linha, mesmo quando estiver escrito em um terminal que não seja. Não há necessidade de chamar um novo bc
para cada cálculo - especialmente em uma substituição de comando que também envolve chamar um novo shell e alocar um novo pipe.
A melhor maneira é configurar um co-processo.
# in a bash shell
exec 8<> >( : ) 9< <( bc <&8 )
echo 'b=5;++b' >&8
read b <&9
echo "$b"
6
E o bc
continuará sendo executado - todos esses valores de variáveis que você está fazendo muito trabalho para ir e voltar entre processos bc
de comando substituíveis e efêmeros poderiam ser armazenados centralmente mais facilmente em uma% centralbc
.
echo b\*b >&8; read b <&9; echo "$b"
32
E, melhor ainda, desde que aprendi a fazer isso no outro dia, você poderia colocar o processo bc
em um servidor de soquete.
{ ncat -l 9000 --allow localhost -k| bc; } <>/dev/fd/1 |:&
E com um shell que fala a linguagem /dev/tcp
:
{ echo 'b=10;b' >&0; read b; echo "$b"; } <>/dev/tcp/localhost/9000
10
Isso pode ficar um pouco complicado. Eu escrevi uma pequena função chamada bchat()
para facilitar.
bchat(){
local IFS=\; ### separate on ;
printf ${1+'%s;"\n"\n';}"$*" ### print BC=/dev/tcp/localhost/9000
bchat b=5 x='(b--)' '"x="' ++x '"b="' --b
echo "$bchat"
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
Depois de configurar um servidor de soquete, como demonstrado acima, você pode usar essa função como:
x=6;b=3
# in a bash shell
exec 8<> >( : ) 9< <( bc <&8 )
echo 'b=5;++b' >&8
read b <&9
echo "$b"
... e, novamente, esse estado persistirá enquanto o processo bc ...
Tenha em atenção que, quando definir a escala, tem influência no cálculo.
Este 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
saídas:
.2061073736
.2061073739
.2061073738
.206107373853763
Tags bc shell shell-script math