Um problema sobre a expressão longa

3

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ê?

    
por yuxuan 13.12.2015 / 22:38

3 respostas

3

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 '…' ).

    
por 13.12.2015 / 22:55
2

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 ...

    
por 14.12.2015 / 01:17
1

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
    
por 15.12.2015 / 23:13