Qualquer maneira de personalizar a inicialização de variáveis na calculadora bc?

1

A calculadora bc parece atribuir às variáveis não inicializadas o valor zero. Eu gostaria de alterar esse comportamento para que, quando bc encontrar uma variável não inicializada, em vez disso, sinalize a expressão como inválida. Por exemplo, no código a seguir,

echo "foo + bar" | bc -l

bc atribui o valor 0 a foo e bar e retorna "0". Eu gostaria que retornasse a string vazia "" ou de alguma outra forma indicasse que "foo + bar" é uma expressão inválida. Existe uma maneira de conseguir isso em bc?

    
por scolfax 09.08.2015 / 12:43

2 respostas

1

Para responder a minha própria pergunta, bloqueando uma maneira de sinalizar variáveis não declaradas como inválidas em bc, criei uma solução viável caso seja útil para outras pessoas. A expressão a ser executada por bc é primeiramente canalizada através de um comando sed, que retira quaisquer palavras bc reservadas da expressão. Quaisquer nomes de variáveis restantes são considerados variáveis não declaradas, e toda a expressão é convertida em uma instrução que forçará um erro quando executada em bc (eu escolhi '1/0', mas qualquer um de um número de sinalizadores de erro alternativos poderia ser construído .)

Gera um erro "Dividir por zero" em tempo de execução:

echo 'foo + bar' | sed -E '
    ## Save the original expression in the hold space
    h
    ## Recursively replace all bc reserved words with a unique token string (¦§§¦)
    :again
    s/auto|break|continue|define|else|for|halt|ibase|if|last|length|limits|obase|print|quit|read|return|scale|sqrt|warranty|while/¦§§¦/g
    s/(a|c|e|j|l|s)([(][^)]*[)])/¦§§¦/g
    t again
    ## If the expression contains any bc reserved words abutting one another, mark the expression as invalid, and skip to the end of the sed script
    /¦§§¦¦§§¦/s/^.+$/1\/0/
    t
    ## Replace all tokens with spaces
    s/¦§§¦/ /g
    ## If any variable names remain, treat them as undeclared variables, mark the expression as invalid, and skip to the end of the sed script
    ## Prior to doing this, reset the t command so that it can recognize if a substitution takes place in the s command
    t reset
    :reset
    /[a-z][a-z0-9_]*/s/^.+$/1\/0/
    t
    ## If the expression does not have undeclared variable names, get the original expression from the hold space
    g
' | bc -l

Retorna a resposta correta = 246:

echo '123 + 123' | sed -E '
    ## Save the original expression in the hold space
    h
    ## Recursively replace all bc reserved words with a unique token string (¦§§¦)
    :again
    s/auto|break|continue|define|else|for|halt|ibase|if|last|length|limits|obase|print|quit|read|return|scale|sqrt|warranty|while/¦§§¦/g
    s/(a|c|e|j|l|s)([(][^)]*[)])/¦§§¦/g
    t again
    ## If the expression contains any bc reserved words abutting one another, mark the expression as invalid, and skip to the end of the sed script
    /¦§§¦¦§§¦/s/^.+$/1\/0/
    t
    ## Replace all tokens with spaces
    s/¦§§¦/ /g
    ## If any variable names remain, treat them as undeclared variables, mark the expression as invalid, and skip to the end of the sed script
    ## Prior to doing this, reset the t command so that it can recognize if a substitution takes place in the s command
    t reset
    :reset
    /[a-z][a-z0-9_]*/s/^.+$/1\/0/
    t
    ## If the expression does not have undeclared variable names, get the original expression from the hold space
    g
' | bc -l

Editar nota: este é um refinamento do meu envio original e é mais preciso na detecção de nomes de variáveis não declaradas.

    
por 12.08.2015 / 07:34
0

Considere usar expr ?

$ expr foo + bar
expr: non-integer argument
$ expr 1 + 5
6
    
por 09.08.2015 / 13:11

Tags